I am working on an iPhone app which is using an external library for which I have the source. During debugging some of the objects are listed as 0x0 in the debugger but the app runs fine. Also, some of the objects addresses point to the wrong thing.
These symbols are in the external library. The addresses are fine if I am tracing through a file actually in the external library.
Does anyone have suggestions how to stop this behavior?
UPDATE: target settings > Build tab > GCC 4.2 Code Generation > "Compile for Thumb"
I turned off this target setting and the gdb problem went away.
--
Hi John.
I understand what you're referring to. I'm also seeing a problem where gdb and NSLog() are giving me different results for pointers in certain parts of my code.
In a boiled-down example, gdb fails to report the proper value for "pointer" when I set a breakpoint on any line in this function:
id testPointer( id pointer )
{
NSLog( #"pointer value: %p", pointer );
#try
{
NSLog( #"foo" );
}
#catch ( NSException *e )
{ }
#finally
{ }
return pointer;
}
As zPesk notes, 0x0 is nil, which is a common value for objects that have not been initialized (particularly instance variables). I'm not certain what you mean by "point to the wrong thing." If you haven't initialized a local (stack) variable, it may point to any random address until it is initialized. What behavior are you having trouble with?
Were you ever able to resolve this issue? I, too, am noticing strange behavior in gdb when mixing Thumb and ARM modes. For example, it appears that the addresses of variables reported by gdb are off by exactly 64 bytes from the addresses reported using printf("%p\n") statements. Perhaps gdb needs to be explicitly told whether the current operating mode is ARM or Thumb...?
Related
Unable to determine what is going on with this error.
I am uploading a file in multiple segments.
I have threaded my api calls into 7 concurrent threads.
Here is the assembly code that it stops at.
Here is my printed stack trace
Finally the Stack window
I do not have any DISPATCH_QUEUE_PRIORITY_LOW except for a #define for dispatch_get_low() and I do not have any calls to dispatch_get_low()
as a little background, I am developing my app from xcode 4.4 and recently installed GM Seed 4.5 to test on ios 6. All of my code is still ios5 and this bug plagued me before and after the update of xcode.
UPDATE
After adding back NSZombieEnabled YES to my environment variables
I was presented with a different error in much the same fashion, This one however is called forwarding
Assembly breakpoint
Stack Trace Printout
Call Stack Window
I am still at a loss as to what is actually going on.
I am still investigating. any further assistance will be much appreciated.
==== New Developments ====
Apparently while trying to get some output of the malloc calls. I completely alleviated the bug.
This is disheartening because I dont think I can compile for release with this flag enabled.
the EXC_BAD_ACCESS no longer appears, therefore the log is going to be useless. This bug is turning out to be the weirdest problem I have faced yet, And I have faced a lot of weird iOS bugs.
Update again
I have been tracking this error down. Turns out the object being a problem is a -[CFNumber release] call The number is being created in a block, then being passed down to the delegate.
It may also be combined with the Core Data object saving and then going away.
I have added a method HSLogBrute(#"") which logs the line number and filename.
I have tracked it down to the following code.
if (progressMatch > progressPercent){
HSLogBrute(#"");
TransferStatus *transferStatus = [TransferStatus objectByID:task.transferStatusID];
HSLogBrute(#"");
transferStatus.segmentsTransferred = [NSNumber numberWithInt:segmentsTransferred.intValue];
HSLogBrute(#"");
transferStatus.segmentsTotal = [NSNumber numberWithInt:segmentsTotal.intValue];
HSLogBrute(#""); // This is the last log I am getting.
[transferStatus save];
HSLogBrute(#"");
}
HSLogBrute(#"");// Before putting in the [NSNumber numberWithInt:] calls this was the last line.
Turns out we were creating an NSMutableDictionary and using numbers within it. Creating and Destroying NSNumbers as fast as we were doing seems to have confused arc at some point. And the objects were being retained and released out of order.
My solution has been to create a custom object that has the numbers that I need within it. And increment and decrement those primitive number types rather than create and destroy so many NSNumber values.
I have a wxWidgets/GTK based application that works well - except for one installation on an Debian Squeeze ARM system. There it crashes when the user just activates the main window of it. To find the reason for that I added a signal handler to the application and use libunwind out of that signal handler to find the source for the crash. During a test that worked fine, when the software writes e.g. to address 0x0 libunwind correctly points me to the function where that happens.
But the results for the system where the crash appears unexpectedly are a bit strange, they seem to happen outside of my application. One crash comes from a function with no name (here libunwind returns an empty string), and one is caused by "malloc_usable_size", a system function which should never die this way.
So...what to do next? All ideas, suggestions or any other hints are welcome since I'm not sure how to contunue with that problem...
Check for buffer overrun or overwriting some memory unexpectedly for any structures, pointers, memory locations for items returned by library functions.
Check for invalid pointer frees in your code for the library allocated pointers that you are using.
May be using valgrind would also help.
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.
I have a simple question about debugging on Xcode and GDB.
I often run into an error:
unrecognized selector sent to instance 0x1081ad0
which makes the program load into GDB. Is there an easy way to examine what instance is located in that memory from GDB?
po 0x1081ad0
po = Print Object.
You can even call methods, like
po [myArray objectAtIndex:0]
Note that it only works on objects, so
po 1
will crash your program.
Steven is correct — the gdb command po is a shortcut for print-object, which actually calls -debugDescription (not -description, as you might expect) on the object provided as an argument. In many cases you'll see the same result from both methods, since one calls the other unless overridden. (See the related Note: callout on this Apple technote for details. Note that in their code sample, po $r3 prints the contents of a PowerPC register, but you can use any object pointer/reference, including Intel registers, etc.)
Also, be aware that print-object will only work on valid objects that haven't been deallocated. It won't help at all if you're sending a message to a borked pointer. Given the error you cited, though, it would seem that it's a valid object instance, it just doesn't implement the method you're trying to invoke.
It's also remotely possible that the object has already been destroyed. This answer should help in that case.
Edit:
There are other ways to "examine" objects in the debugger. I asked this SO question about Xcode data formatters, which is one way you can determine how a custom class appears in the Summary column of the debugger. The documentation linked from that question explain how it works. I've found the summary approach to help a lot with seeing the state of an object.
There are a couple of things you can do.
You can insert a break point that will trigger every time you have an exception, so basically create a break point for this (go to breakpoints and create a new one): -[NSException raise]
Alternatively, you can actually see what the object at that mem location is:
info symbol 0x1081ad0 or
info line *0x1081ad0
There's more info at the cocoadev wiki entry for exceptionhandling and debugging tips for objective C at cocoawithlove.
Your instance is not valid. You have release the object somewhere else, but you did not clear out your pointer... enable Zombie detection.
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).