Re: Tracking down SIGABRTs
Re: Tracking down SIGABRTs
- Subject: Re: Tracking down SIGABRTs
- From: Don Quixote de la Mancha <email@hidden>
- Date: Sun, 29 Apr 2012 22:26:17 -0700
On Sun, Apr 29, 2012 at 8:00 PM, Don Quixote de la Mancha
<email@hidden> wrote:
> Place some assertions as the very first executable lines in each of
> your subroutines. The chances are quite good that the cause of the
> SIGABRTs are executable quite a long time before the crashes actually
> happen.
...
> #include <assert.h>
>
> void foo( int *ptr )
> {
> assert( NULL != ptr );
> ...
> return;
> }
While asserting that a pointer which must not be NULL actually isn't
NULL, that's quite a permissive test and does not help at all for
pointers which may be NULL.
A pointer may be given an invalid value quite a long time before it
causes a problem, and a value may initially be valid only to become
invalid much later when the heap block it points to (or points into
the middle of) is disposed.
A stricter test is to actually dereference the pointer by reading from
it. It's best to read in the entire block that it points to, if you
know it's type. While less strict, far quicker and easier is to cast
it to a char or unsigned char then read that:
BOOL checkPointer( void const *p )
{
unsigned char val = *(unsigned char*)p;
return TRUE;
}
You'll see that that test always returns true, but if your pointer
points into unmapped memory, you will get a crash right there.
I have a bunch of these kinds of tests in libmdc:
http://www.goingware.com/libmdc/
While libmdc is mostly C++ templates, even if you don't know C++ the
code is so straightforwad it should be easy to figure out for anyone
who knows any "Curly Brace" language.
Even if the memory is mapped, if you run your app under Guard Malloc
or Valgrind, reads of memory which is mapped but not allocated in some
way will cause a crash.
Your pointer may point into memory which is mapped but read-only, such
as executable code or read-only memory mapped data. In that case, IF
YOU CAN BE SURE ONLY ONE THREAD IS ACCESSING THAT DATA! read in a byte
to save its original value, write a value into the pointer, then
restore the original value:
BOOL checkWriteablePointer( void *p ) // NOT const pointer!
{
unsigned char save = *(unsigned char*)p;
*(unsigned char*)p = 0xbe;
*(unsigned char*)p = save;
return TRUE;
}
Even if it's a const pointer, but you can be sure that the underlying
memory that is storing the value is itself writeable, you can cast a
const pointer to a non-const one. For C++ or Objective-C++ you should
use const_cast to make it clearer what you are doing.
If your pointer claims to point to any particular kind of object, then
verify that it really does point to that kind of object! For C++ use
dynamic_cast, for Objective-C use class and isKindOfClass. There's a
real good discussion of that at StackOverflow:
http://stackoverflow.com/questions/1374168/is-there-an-equivalent-to-cs-dynamic-cast-in-objective-c
While to the best of my knowledge it's not actually enforced either by
the compiler or the runtime, the convention in Objective-C is that
non-nil id pointers MUST point to Objective-C OBJECTS and not just to
any kind of data, even if they point to completely valid memory.
You can enforce this by calling some method which is in the base class
NSObject then asserting you got some rational result, or for general
(not Cocoa or Cocoa Touch) Objective-C Object.
--
Don Quixote de la Mancha
Dulcinea Technologies Corporation
Software of Elegance and Beauty
http://www.dulcineatech.com
email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden