On Sun, Apr 29, 2012 at 8:00 PM, Don Quixote de la Mancha <quix...@dulcineatech.com> 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 quix...@dulcineatech.com _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com