2

I've been putting on with a strange issue in my iPhone program for a while.

To make long story short: I have an XML which contains data about tree-like composition. I've wrote a parser which constructs a tree from the XML.

Somewhere in DataSource class I have following method:

 - (id)loadAllData {
   if (self.doc != nil) {
    GDataXMLElement *root = [self.doc rootElement];
    Component *component = [Component componentWithRoot:root];
    NSLog(@"%@", component);
    return component;
  }
  return nil;
}

Factory method looks like this:

+ (id)componentWithRoot:(GDataXMLNode*)element {
  id<iComponent> component = nil;
  NSString *clsName = [NSString stringWithFormat:@"%@Element", [element name]];

  // Will return instance of a class or |nil| if class is not loaded.
  Class cls = NSClassFromString(clsName);

  if (cls != nil) {
    component = [[cls alloc] init];

    // dies on next line
    NSLog(@"created %@", component);

    // Seems that we have corresponding model class
    if (component != nil) {

      //... setting attrubutes for this model

      //... trying to find child elements and add them to the component instance.
    }
  }
  return component;
}

Also when I stop GDB on line where I call alloc and init methods and try to call them in debugger I see next error log:

(gdb) po component

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x828282df
0x01052a67 in objc_msgSend ()
The program being debugged was signaled while in a function called from GDB.
GDB has restored the context to what it was before the call.
To change this behavior use "set unwindonsignal off"
Evaluation of the expression containing the function (_NSPrintForDebugger) will be abandoned.

So the situation is: somehow my program starts up and displays values that I need correctly. But when I try to do something with my component, program just crashes. Any ideas? How can I find a error? I don't any reasons why NSLog(@"created %@", component); crashes application and so do other actions with component (actually I want to encode it to an archive).

Thanks in advance!


Update

This is piece of factory method code with comments

+ (id)componentWithRoot:(GDataXMLNode*)element {
  id<iComponent> component = nil;
  NSString *clsName = [NSString stringWithFormat:@"%@Element", [element name]];
  NSLog(@"%@", clsName);
  // Will return instance of a class or |nil| if class is not loaded.
  Class cls = NSClassFromString(clsName);
  if (cls != nil) {
    component = [[[cls alloc] init] autorelease];
    // Seems that we have corresponding model class
    if (component != nil) {

      [component setTitle:[element name]]; 
      /*
       when I run app I have first element named ConfigElement. 
       Code runes fine to this point and even properties are set correct.
       But if I set breakpoint at this line and type in consle 
         po component
       I get message which is posted below
      */ 

(gdb) po component

Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x828282df 0x01052a67 in objc_msgSend () The program being debugged was signaled while in a function called from GDB. GDB has restored the context to what it was before the call. To change this behavior use "set unwindonsignal off" Evaluation of the expression containing the function (_NSPrintForDebugger) will be abandoned.

Since this happens I want to make sure that all init methods are correct. Here what I am doing:

first - check that name of class is ConfigElement - yes

second - look at ConfigElement init - everything ok:

- (id)init {
  self = [super init];
  return self;
} 

third - look at super (Composite) initializer:

- (id)init {
  if ((self = [super init])) {
    children_ = [[NSMutableArray alloc] init];
  }
  return self;
}

then look for super initializer again (Component initializer now) - seems good again:

- (id)init {
  if ((self=[super init])) {
    title_ = nil;
    name_ = nil;
    icon_ = nil;
    parent_ = nil;
    children_ = nil;
  }
  return self;  
}

Since Component is a subclass of NSObject I don't need to bother about super initializer again and could probably remove if statement but let it be. Also all these initilizers are designated and they are actually called at the moment of init.

So why I am getting that error msg in GDB?

9
  • 2
    What happens if you do NSLog(@"component %@", cls) after the cls != nil line? Also, why are you using this rather than the built in serialization/archiving tools? Commented Apr 5, 2011 at 14:27
  • You're leaking memory here. Unless your factory method is called something like "new", "copy", or "create" then it should return an autoreleased object. As to why it's crashing, I'm not sure. Commented Apr 5, 2011 at 14:45
  • @toiletseat I need to use this because I can't store objects in simple plist due to compatibility needs. Answering your question - program just dies. I don't see any reasons because I've imported corresponding classes before, clsName was set correctly, cls also is not null. And when I do cls alloc nothing but correct pointer should be returned, am I right? Commented Apr 5, 2011 at 15:46
  • 1
    @Dig, have you overridden the init method in the classes that Component instantiates? Are you definately returning self from the init method? Does it work if you hard-code in the name of a class you are trying to instantiate? I'd be interested in seeing the init method of a class you are trying to instantiate that fails. Commented Apr 5, 2011 at 16:18
  • 1
    @Dig, the exception you are getting (in objc_msgSend) generally means you are sendnig a message to an object that has been freed, or isn't actually a valid object (ie an int, or a random area of memory). The error is happening when you call the description method on your object, either via NSLog or the GDB po, I don't suppose you've override description in your Component class heirarchy? I'll download your source and have a look. Commented Apr 6, 2011 at 11:19

2 Answers 2

2

The problem was in my buggy description method:

- (NSString*)description {
  NSString *desc = [NSString stringWithFormat:@"Title: %@, Name: %@, Icon: %@, parent: %@, children: %@", self.title, self.name, self.icon, self.parent];
  return desc;
}

Once this method was fixed, debugger started to print correct values.

Sign up to request clarification or add additional context in comments.

Comments

0

Both componentWithRoot: and loadAllData should be returning an autoreleased object.

What toiletseat said are all good suggestions/questions. This sounds specifically like a problem internal to your Component class. Would have to see its innards to say more.

1 Comment

Hi, thanks for attention, yes I undestand that it is surely my implementation errors, but can't detect them at the moment. Posted my classes here gist.github.com/904194

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.