PDA

View Full Version : Strategies for debugging a SIGABRT




GorillaPaws
Mar 7, 2012, 07:28 PM
I ran into a bug last night with a SIGABRT. I was convinced it had to do with passing an enum as a parameter since I don't have much experience with enums besides when I first learned about them. When I replaced the enums with #defined constants, and was getting the same crash, I realized I was falling for the old "the problem is not where you think it is" mistake that is so easy to make.

It turns out that the value I was setting with the enum was using a constant key defined in an external constant file that didn't match the key in the core data model. This whole story leads me to the question, when you get a SIGABRT crash, what are some of the things that immediately spring to mind as to the potential causes? Also, why did my bug result in a SIGABRT crash instead of an EXC_BAD_ACCESS?



jared_kipe
Mar 7, 2012, 11:51 PM
I don't have a complete understanding of these things, but EXEC_BAD_ACCESS could be a general segmentation fault like trying to address virtual memory you don't actually have. Or trying to send a message to an object that doesn't exist. Or if you mess up the stack pointer...

Sigabrt is basically some library function (or the OS) calling abort(); because it has decided life cannot go on.

GorillaPaws
Mar 8, 2012, 02:56 AM
Thanks for the response. So SIGABRT isn't in response to an anticipated failure case, but is thrown when there is a gross inconsistency? If it's an anticipated failure case, why wouldn't it throw an exception instead?

My memory of KVO/KVC is a bit fuzzy, but I thought when you're trying to use an unrecognized key, it walks up the inheritance hierarchy asking if the object responds to selector and then throws an exception if the root object doesn't?

jared_kipe
Mar 8, 2012, 10:52 AM
The easiest way to cause sigabrt that I can think of is to mess up the heap and then make a call to malloc.


char *test = malloc(4);
for (int i = 0; i < 300; i++) {
test[i] = 1;
}
char *break = malloc(4);
printf("hello\n");


The second malloc() will sigabrt. If you comment out the char *break line, this will function fine assuming no other heap calls or objects need to be made later...
If you comment out char *break, and replace printf with a call to NSLog you'll get sigabrt again. Indicating that NSLog probably does a call to malloc or needs to use something in the heap thats been trashed by my 'agressive' for loop.

For the record the easiest way to cause a EXEC_BAD_ACCESS on most platforms would be to simply put a very low constant into a pointer and try to dereference it.

int *t;
t = (int *)1; // perfectly fine, it is 'a' memory address...
*t = 1; // bad access, because you don't own that address :'(