iPhone OS memory problem - how to debug? - iphone

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?

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.

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_Simulator_Valgrind.20081224.html
You may have to change the VALGRIND path in the code example depending on where it gets installed.

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.

Related

release build variable corruption when using ne10 math library assembly function

has anyone experience the following issue?
A stack variable getting changed/corrupted after calling ne10 assembly function such as ne10_len_vec2f_neon?
e.g
float gain = 8.0;
ne10_len_vec2f_neon(src, dst, len);
after the call to ne10_len_vec2f_neon, the value of gain changes as its memory is getting corrupted.
1. Note this only happens when the project is compiled in release build but not debug build.
2. Does Ne10 assembly functions preserve registers?
3. Replacing the assembly function call to c equivalent such as ne10_len_vec2f_c and both release and debug build seem to work OK.
thanks for any help on this. Not sure if there's an inherent issue within the program or it is really the call to ne10_len_vec2f_neon causing the corruption with release build.enter code here
I had a quick rummage through the master NEON code here:
https://github.com/projectNe10/Ne10/blob/master/modules/math/NE10_len.neon.s
... and it doesn't really touch address-based stack at all, so not sure it's a stack problem in memory.
However based on what I remember of the NEON procedure call standard q4-q7 (alias d8-d15 or s16-s31) should be preserved by the callee, and as far as I can tell that code is clobbering q4-6 without the necessary save/restore, so it does indeed look like it's clobbering the stack in registers.
In the failed case do you know if gain is still stored in FPU registers, and if yes which ones? If it's stored in any of s16/17/18/19 then this looks like the problem. It also seems plausible that a compiler would choose to use s16 upwards for things it needs to keep across a function call, as it avoids the need to touch in-RAM stack memory.
In terms of a fix, if you perform the following replacements:
s/q4/q8/
s/q5/q9/
s/q6/q10/
in that file, then I think it should work; no means to test here, but those higher register blocks are not callee saved.

What can I do to find out what's causing my program to consume lots of memory over time?

I have an application using POE which has about 10 sessions doing various tasks. Over time, the app starts consuming more and more RAM and this usage doesn't go down even though the app is idle 80% of the time. My only solution at present is to restart the process often.
I'm not allowed to post my code here so I realize it is difficult to get help but maybe someone can tell me what I can do find out myself?
Don't expect the process size to decrease. Memory isn't released back to the OS until the process terminates.
That said, might you have reference loops in data structures somewhere? AFAIK, the perl garbage collector can't sort out reference loops.
Are you using any XS modules anywhere? There could be leaks hidden inside those.
A guess: your program executes a loop for as long as it is running; in this loop it may be that you allocate memory for a buffer (or more) each time some condition occurs; since the scope is never exited, the memory remains and will never be cleaned up. I suggest you check for something like this. If it is the case, place the allocating code in a sub that you call from the loop and where it will go out of scope, and get cleaned up, on return to the loop.
Looks like Test::Valgrind is a tool for searching for memory leaks. I've never used it myself though (but I used plain valgrind with C source).
One technique is to periodically dump the contents of $POE::Kernel::poe_kernel to a time- or sequence-named file. $poe_kernel is the root of a tree spanning all known sessions and the contents of their heaps. The snapshots should monotonically grow if the leaked memory is referenced. You'll be able to find out what's leaking by diff'ing an early snapshot with a later one.
You can export POE_ASSERT_DATA=1 to enable POE's internal data consistency checks. I don't expect it to surface problems, but if it does I'd be very happy to receive a bug report.
Perl can not resolve reference rings. Either you have zombies (which you can detect via ps axl) or you have a memory leak (reference rings/circle)
There are a ton of programs to detect memory leaks.
strace, mtrace, Devel::LeakTrace::Fast, Devel::Cycle

Why does Cocoa return an empty string occasionally?

I have some code in my application that looks something like this:
char *hash = (char*) sqlite3_column_text(get_bookmark, 0);
NSString* postHash = [NSString stringWithUTF8String:hash];
This works for me every time; I've never seen it not work. Most of my users do not experience problems (as far as I know). However I find that postHash is an empty string (#"") for some users some of the time.
Can anyone explain why?
Some more context/speculation:
This only seems to happen on jailbroken handsets. Is there anything different about them? I gather that there's usually less memory available. Anything else that could contribute here?
postHash is used in a table cell and is occasionally seen to be populated correctly so I'm reasonably confident that the database call should work. In fact, if the database also has an empty string it's because of a very similar piece of code so the question remains.
hash is certainly returning with a non-NULL value. If I force a NULL here, the app crashes. Similarly, postHash is not nil as that would also crash the app (for the same reason).
I am thinking that this is possibly memory related. If the method tries to allocate too much memory before -didReceiveMemoryWarning can get called what happens? I know that, at some point, the Springboard ejects the app. But is it possible that Cocoa returns a null string here rather than the expected value? I've heard of a few reports that, as far as I can tell, can only have been caused by an empty string being present where something longer should have been present.
Any other speculation, theories or ideas welcome.
However I find that postHash is an empty string (#"") for some users some of the time.
Can anyone explain why?
Because hash is an empty string (hash[0] == '\0').
I finally found the solution to this. I'm going to give Peter the accepted answer as he is right but the reason that I was getting an empty string is... interesting.
The database is populated correctly. The query is also correct. The difference between my phone and my users is that they have jail broken handsets. And apparently jail broken iPhones sometimes use a different version of SQLite than found in shipping versions of iPhone OS.
The change in version exposed a bug in my code that caused one of the parameters to be set incorrectly and sqlite3_column_text to return an empty string.

How can I find memory leaks in long-running Perl program?

Perl uses reference counting for GC, and it's quite easy to make a circular reference by accident. I see that my program seems to be using more and more memory, and it will probably overflow after a few days.
Is there any way to debug memory leaks in Perl? Attaching to a program and getting numbers of objects of various types would be a good start. If I knew which objects are much more numerous than expected I could check all references to them and hopefully fix the leak.
It may be relevant that Perl never gives memory back to the system by itself: It's all up to malloc() and all the rules associated with that.
Knowing how malloc() allocates memory is important to answering the greater question, and it varies from system to system, but in general most malloc() implementations are optimized for programs allocating and deallocating in stack-like orders. Perl uses reference-counting for tracking memory which means that deallocations which means (unlike a GC-based language which uses malloc() underneath) it is actually not all that difficult to tell where deallocation is going to occur, and in what order.
It may be that you can reorganize your program to take advantage of this fact- by calling undef($old_object) explicitly - and in the right order, in a manner similar to the way C-programmers say free(old_object);
For long-running programs (days, months, etc), where I have loads of load/copy/dump cycles, I garbage-collect using exit() and exec(), and where it's otherwide unfeasible, I simply pack up my data structures (using Storable) and file descriptors (using $^F) and exec($0) - usually with an environment variable set like $ENV{EXEC_GC_MODE}, and you may need something similar even if you don't have any leaks of your own simply because Perl is leaking small chunks that your system's malloc() can't figure out how to give back.
Of course, if you do have leaks in your code, then the rest of my advice is somewhat more relevant. It was originally posted to another question on this subject, but it didn't explicitly cover long-running programs.
All perl program memory leaks will either be an XS holding onto a reference, or a circular data structure. Devel::Cycle is a great tool for finding circular references, if you know what structures are likely to contain the loops. Devel::Peek can be used to find objects with a higher-than-expected reference count.
If you don't know where else to look, Devel::LeakTrace::Fast could be a good first place, but you'll need a perl built for debugging.
If you suspect the leak is inside XS-space, it's much harder, and Valgrind will probably be your best bet. Test::Valgrind may help you lower the amount of code you need to search, but this won't work on Windows, so you'd have to port (at least the leaky portion) to Linux in order to do this.
Devel::Gladiator is another useful tool in this space.
Seems like the cpan module Devel::Cycle is what you are looking for. It requires making some changes to your code, but it should help you find your references without too many problems.
valgrind is a great linux application, which locates memory leaks in running code. If your Perl code runs on linux, you should check it out.
In addition to the other comments, you may find my Perl Memory Use talk at LPW2013 useful. I'd recommend watching the screencast as it explains the slides and has some cute visuals and some Q&A at the end.
I'd also suggest looking at Paul Evans Devel::MAT module which I mention in the talk.

Error in device but not in simulator

I have this line of code (splits is an instance variable):
splits = [[NSMutableArray alloc] initWithObjects:[NSMutableArray array]];
This code is obviously wrong (it should be nil-terminated), however it runs fine in the simulator, even though it throws an EXC_BAD_ACCESS on the device. My question is why does the simulator not throw an error?
Kyle
The actual outcome depends on the memory contents. It is quite possible that the memory layout on the simulator contains a zero right after the address of the first parameter (the anonymous array). This zero gets interpreted as if you would close the argument list with nil and everything works fine. (P.S. There is an interesting macro called NS_REQUIRES_NIL_TERMINATION for such cases, although it obviously would not help here.)
The iPhone has much less memory than your computer. The area in memory for the stack could have been set to 0x00 (nil) before being used by the initWithObjects function. When the parameters are sent to the initWithObjects function and the stack is alloated, that memory space on the computer is more likely to be preset to 0x00 than the iPhone because the same memory space is used less often. So it is likely that the nil is being read from a spot in memory set to 0 already.
If you fill up your memory on your computer, and then run the simulator, the simulator may be more likely to crash like the iPhone.
Buffer overflows result in undefined behavior. They are not guaranteed to cause an access violation (or even a noticeable bug). On modern machines, they will cause an access violation if you happen to step on "someone else's" memory, but probably not if you're just reading junk from your own stack.
Basically, you just need to be careful, and can try tools like Mudflap and Valgrind to help you out (these particular two are more meant for C/C++, and I don't know how well they apply to Obj-C).