views:

289

answers:

3

I have a pretty weird problem in my iPhone app which is, I think, related to memory getting corrupted:

At one point, I need to sort an array, which I do with -[sortArrayUsingFunction].

The result is not correct unless I either allocate some memory with something like void *test = malloc(2 * sizeof( int )) before the method call or have, e.g., a call to NSLog() (which is never invoked) in the sorting function.

In other words: the sorting only works if I slightly increase the memory that was used before calling the sorting function. I think this is because at some point, memory gets corrupted.

How do you debug something like this?

A: 

Such things can be a challenge to debug. There are some tools for detecting out-of-bounds accesses and such on other platforms, so I presume there would be something for the iPhone, however I don't know of any.

Perhaps you should store two copies of the array, and compare them for differences. Print out the differences. The nature of the "junk" that was introduced to one of the arrays might give a hint as to where it came from.

Also just go through the code that runs before this point, and re-read it (or better yet, get someone else to read it). You might spot a bug.

Artelius
+1  A: 

It sounds like some of your code is using already released objects. A lot of help with debugging this kind of errors is provided in Apple’s great Mac OS X Debugging Magic tech note, especially the foundation part.

For your case I'd disable autorelease pools (setting the environment variable NSEnableAutoreleasePool=NO) or use the zombie feature (NSZombieEnabled=YES) to find places where you send messages to released objects.

Nikolai Ruhe
The problem seems to disappear when I set NSEnableAutoreleasePool=NO. But I don't get any messages when setting NSZombieEnabled and if I don't set NSEnableAutoreleasePool to NO, but set the pool to nil in main.m (which should be equivalent), the problem is still there... Everything is still very weird, but autorelease _might_ be the problem.
mrueg
Okay, now you now that over-releasing is probably the problem. First try the static analyzer (clang). Then, if you don't find the problem, start looking at suspicious objects and retain them. If the problem then goes away, you know which object is released before its time.
Nikolai Ruhe
B.t.w.: Of course you must enable autorelease pools when enabling zombie detection.
Nikolai Ruhe
I tried clang when the problem first appeared, to no avail, it seems to think my code is just fine. (I also cleaned the project before running it.) The problem seemed to be completely gone when I removed all release calls in my project, but when I re-started the app, I saw that it was just the symptom temporarily disappearing. I'm now pretty sure that the problem is not with over-releasing or autoreleases. But what other way to corrupt memory is there in Obj-C code?
mrueg
There are lots of ways to break things—it's C, after all. But what makes you sure that it’s not a retain/release problem?
Nikolai Ruhe
+2  A: 

Try running your program in the simulator under Valgrind:

http://valgrind.org/

And how to use it under the simulator:

http://landonf.bikemonkey.org/code/iphone/iPhone%5FSimulator%5FValgrind.20081224.html

You may have to change the VALGRIND path in the code example depending on where it gets installed.

EricS