tags:

views:

429

answers:

5

Hi,

I'm doing an iPhone application which uses a navigation control to browse through some data. This data is stored in a sqlite database and I have a class which gets it and returns it in a NSMutableArray of NSStrings.

The problem is that in the first screen of the navigation everything works prefectly, but in the second screen (another view which is pushed) the same code fails because the NSMutableArray gets corrupted. In the debugger I can see that it is returned correctly, but when it's time to use it the pointers have become corrupted and the application crashes.

I have put breakpoints in all my functions, and I can't see anywhere where it can get corrupted. And as the first view, which uses the same exact code, even accesing the same eact tables, works correctly I don't really know where to look.

If anyone want to have a look at the code I have uploaded it to my site: http://sachafuentes.com/iBacus.zip

Thanks in advance.

UPDATE:

The problem lies in the function where I get the data, which looks like (this is a simplified version with some pseudo-code).

-(NSMutableArray *) getPaises {
 NSMutableArray * paises;
 paises = [[NSMutableArray alloc] init];
 while( get new row ) {
  NSString *aPais = get the value;
  [paises addObject:aPais];
  [aPais release];
 }
 return paises;
}

If I comment out [aPais release] everything works, but to me this looks like a memory leak, as the NSString won't be released.

+1  A: 

Look for wrong memory management, that's the likeliest cause for crashes. I think you release your objects somewhere where you shouldn't and therefore you have dangling pointers in the array.

Update1

[aPais release] is wrong, as you don't retain it anywhere in this method. Returned values should always be autoreleased. You should have the same amount of retain as release in your code.

(Some people argue that a retain can also be an alloc init, but I always try to use alloc init autorelease, but this is a matter of style.)

BTW

You should autorelease your array, you're only retaining it here with [[alloc] init].

Georg
You are right, the problem is that I don't know why it fails, probably I have a wrong concept of something. I have added to the question some code to exemplify the problem. Thanks anyway for your help.
Sacha Fuentes
+1  A: 

Any object that you alloc and init must be release-d when you're finished with it, or you will have a memory leak.

Since you are passing the reference outside the scope of the getPaises method, you must autorelease the NSMutableArray, or you will have a memory leak:

paises = [[[NSMutableArray alloc] init] autorelease];

Can you please clarify the step here:

NSString *aPais = get the value;

It's not clear what happens in "get the value" and I suspect this is one cause of instability.

Alex Reynolds
+1  A: 

I see that the code is (verbatim)

while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
    NSString *aPais = [NSString stringWithUTF8String:
                       (char*)sqlite3_column_text(compiledStatement, 0)];
    [paises addObject:aPais];
    [aPais release];
}

...and it's exactly as @gs puts it. aPais is autoreleased and should not be released.

epatel
+3  A: 

Okay, here's the problem:

NSString *aPais = [NSString stringWithUTF8String:(char*)sqlite3_column_text(compiledStatement, 0)];

By convention, any time that you see an alloc and an init, you need a release somewhere down the road.

By convention, any time that you use an xWithX: style method, the resulting object will be released for you.

Therefore, this statement:

[aPais release];

will cause your method to crash, as the object is released before it should be. Just remove this line, set your NSMutableArray instance to be autorelease-d and you should get better results.

Alex Reynolds
A: 

You can also use a convenience constructor to initialize the NSMutableArray:

NSMutableArray *paises = [NSMutableArray array];

This is equivalent to doing:

NSMutableArray *paises = [[[NSMutableArray alloc] init] autorelease];
toldroyd