views:

42

answers:

4

I'm using a NSDictionary to get a NSString from a plist with the following code:

NSString *fullPath = [[NSBundle mainBundle] pathForResource:@"TestIds" ofType:@"plist"];
NSDictionary *dictionary = [[NSDictionary dictionaryWithContentsOfFile:fullPath] retain];
NSString *testid = [dictionary objectForKey:@"testId"];

and then I save it in a NSMutableArray with objects of a class I created:

// before the code above
NSMutableArray *array = [[NSMutableArray array] retain]; // this is actually a global variable

// after the code
IdDescription *idDesc = [[IdDescription alloc] initWithId:testid];
[array addObject:idDesc];

the application does some stuff with other things and then calls a method which calls the NSString:

IdDescription *desc = [array objectAtIndex:n];
NSLog(@"%@", desc.testId); // testId is a property with retain

The problems is that the application crashes or gets interrupted and all kind of things when it gets to the NSLog line. The most rare thing is that it works if I change the line:

NSString *testid = [dictionary objectForKey:@"testId"];

for:

NSString *testid = @"testId_1";  // or any other string

I tested adding:

if ([testid compare:@"testId_1"] == NSOrderedSame)
    testid = @"testId_1";

after the

 NSString *testid = [dictionary objectForKey:@"testId"]

and it still works.

I also tried using

NSString *testid = [NSString stringWithFormat:@"testId_%d", 1]

instead of the troubling line but it crashes with the same EXC_BAD_ACCESS error.

Anybody knows what could be the problem? I have tried almost everything. Any help is most appreciated.

A: 
NSString *testid = [dictionary objectForKey:@"testId"];

How sure are you that the dictionary contains a value for the key "testId"? Do a NSLog of your dictionary and examine the contents to make sure all is as you expect it will be by that point.

I don't see your IdDescription class so can't see where IdDescription retains testid. Are you using (nonatomic, retain) or similar? If so don't forget you need to use self. when you make the assignment or retain doesn't happen.

EXC_BAD_ACCESS is usually when a message is sent to an object that has been released. You could confirm this by setting NSZombieEnabled YES in your executable's settings.

You might also get some helpful information if you build with the static analyzer, shift-sommand-A. It is better at finding leaks than overrelease issues but if you add a retain in IdDescription for testid and don't get a wrning from it, that's another piece of information suggesting that testid has been released before you had finished using it.

Adam Eberbach
A: 

You haven't really posted enough information but the probability is that either desc is a garbage pointer or desc.testId is a garbage pointer by the time you get to the NSLog() line. Note that if either were nil, the NSLog line would not crash, it would simply print

(null)

Two things you should check.

  1. do you retain testId in the init method
  2. do you return self in the init method.

My bet is that you are not retaining testId since when you replace it with a constant string, the problem goes away (release is a noop for constant strings).

JeremyP
A: 

Try to enable zombies. This message means that a pointer you are using is not an actually objective C object. Most likely because you have forgotten a retain or init.

In the info for the Executable add

NSZombieEnabled YES

Dr. Touch
A: 

I found the problem. In the line NSString *testid = [dictionary objectForKey:@"testId"]; I had to change it to NSString *testid = [[dictionary objectForKey:@"testId"] copy]; since the NSData object was released after all the information was gathered.