Re: test if a pointer is pointing to a valid object or not?
Re: test if a pointer is pointing to a valid object or not?
- Subject: Re: test if a pointer is pointing to a valid object or not?
- From: p3consulting <email@hidden>
- Date: Wed, 29 Oct 2003 15:37:04 +0100
ok, let's go with some code with signal handling:
#import <Foundation/Foundation.h>
#import <Foundation/NSDebug.h>
#import <signal.h>
#import <setjmp.h>
int initialized_static_data = 2 ;
int IsValidObjCPointer_UnInitDataLimit ;
void some_code(const char *message)
{
printf("%s\n", message) ;
}
static sigjmp_buf *SigJmpBufRecover ;
static unsigned CommandLineArgsAddr ;
void SigHandler(int inSignal, siginfo_t *inSigInfo, void *unused)
{
siglongjmp(*SigJmpBufRecover, 1);
}
BOOL IsValidObjCPointerOfClass(id inPtr, Class inClass)
{
unsigned ptrAsInt = (unsigned)inPtr ;
sigjmp_buf sigHandlerJmpBuffer ;
struct sigaction sa_old_SIGSEGV ;
struct sigaction sa_old_SIGBUS ;
struct sigaction sa_new ;
BOOL result = NO ;
if ((ptrAsInt == nil) || ((ptrAsInt % 4) != 0))
return NO ;
if ((ptrAsInt <= CommandLineArgsAddr) && (ptrAsInt >
(unsigned)&result))
return NO ;
sa_new.sa_sigaction = SigHandler ;
sigemptyset(&sa_new.sa_mask);
sigaddset(&sa_new.sa_mask, SIGINT);
sigaddset(&sa_new.sa_mask, SIGALRM);
sigaddset(&sa_new.sa_mask, SIGTERM);
sa_new.sa_flags = SA_SIGINFO | SA_NODEFER ;
sigaction(SIGSEGV,&sa_new,&sa_old_SIGSEGV) ;
sigaction(SIGBUS,&sa_new,&sa_old_SIGBUS) ;
if (!sigsetjmp(sigHandlerJmpBuffer,1)) {
SigJmpBufRecover = &sigHandlerJmpBuffer ;
NS_DURING
result = [inPtr isKindOfClass:inClass] ;
NS_HANDLER
NS_ENDHANDLER
}
sigaction(SIGSEGV,&sa_old_SIGSEGV,NULL) ;
sigaction(SIGBUS,&sa_old_SIGBUS,NULL) ;
return result ;
}
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSZombieEnabled = YES ;
CommandLineArgsAddr = (unsigned)&argv ;
id someObj = [[NSObject alloc] init] ;
NSLog(@"someObj %@ class %@",someObj,[someObj class]) ;
[someObj release] ;
NS_DURING
NSLog(@"released someObj %@ class %@",someObj,[someObj class]) ;
NS_HANDLER
NS_ENDHANDLER
some_code("Hello, World!");
printf("Address of argc 0x%0X argv
0x%0X\n",(unsigned)&argc,(unsigned)&argv) ;
printf("Address of some program text 0x%0X\n",(unsigned)&some_code)
;
printf("Address of some stack variable 0x%0X\n",(unsigned)&pool) ;
printf("Address of some initialized_static_data
0x%0X\n",(unsigned)&initialized_static_data) ;
printf("Address of some uninitialized_static_data
0x%0X\n",(unsigned)&IsValidObjCPointer_UnInitDataLimit) ;
printf("Address of some heap data 0x%0X\n",(unsigned)pool) ;
printf("Is pool ValidObjCPointerOfClass NSAutoreleasePool
%d\n",IsValidObjCPointerOfClass(pool, [NSAutoreleasePool class])) ;
printf("Is 0x55014578 ValidObjCPointerOfClass NSObject
%d\n",IsValidObjCPointerOfClass((void *)0x55014578, [NSObject class]))
;
printf("Is pool ValidObjCPointerOfClass NSArray
%d\n",IsValidObjCPointerOfClass(pool, [NSArray class])) ;
printf("Is nil ValidObjCPointerOfClass NSArray
%d\n",IsValidObjCPointerOfClass(nil, [NSArray class])) ;
printf("Is 0x1 ValidObjCPointerOfClass NSArray
%d\n",IsValidObjCPointerOfClass((void *)0x1, [NSArray class])) ;
printf("Is &pool ValidObjCPointerOfClass NSAutoreleasePool
%d\n",IsValidObjCPointerOfClass((void *)0x1, [NSAutoreleasePool
class])) ;
printf("Is someObj ValidObjCPointerOfClass NSObject
%d\n",IsValidObjCPointerOfClass(someObj, [NSObject class])) ;
[pool release];
return 0;
}
Will output:
2003-10-29 15:29:49.637 TestAppLimits[3517] someObj <NSObject:
0x3009c0> class NSObject
2003-10-29 15:29:49.639 TestAppLimits[3517] *** *** Selector 'class'
sent to dealloced instance 0x3009c0 of class NSObject.
Break at '-[_NSZombie class]' to debug.
Hello, World!
Address of argc 0xBFFFFD38 argv 0xBFFFFD3C
Address of some program text 0x9B394
Address of some stack variable 0xBFFFF910
Address of some initialized_static_data 0x9C000
Address of some uninitialized_static_data 0x9C060
Address of some heap data 0x305790
Is pool ValidObjCPointerOfClass NSAutoreleasePool 1
Is 0x55014578 ValidObjCPointerOfClass NSObject 0
Is pool ValidObjCPointerOfClass NSArray 0
Is nil ValidObjCPointerOfClass NSArray 0
Is 0x1 ValidObjCPointerOfClass NSArray 0
Is &pool ValidObjCPointerOfClass NSAutoreleasePool 0
2003-10-29 15:29:50.320 TestAppLimits[3517] *** *** Selector
'isKindOfClass:' sent to dealloced instance 0x3009c0 of class NSObject.
Break at '-[_NSZombie methodSignatureForSelector:]' to debug.
Is someObj ValidObjCPointerOfClass NSObject 0
TestAppLimits has exited with status 0.
Of course this will not guarantee that it's the pointer that the
programmer expected
but this one is another kind of debugging problem that could be
answered by NSLog,
at least here we could use this routine to test that what we want to
log with "%@" will no crash NSLog.
if (IsValidObjCPointerOfClass(mySuspectedObj,[NSObject class])
NSLog(@"mySuspectedObj %@", mySuspectedObj);
else
NSLog(@"mySuspectedObj is corrupted 0x%0X (no more a valid NSObject)",
mySuspectedObj);
It also depends on what kind of bug we are tracking
At least it will allow some debugging
And of course if you really try to fake it with an address on something
you will build by hand you may be successfull
but at least we have something the original poster may use and its
program will stop crashing and he can log to try to find out where
its object pointer was "corrupted"
Note the printed values regarding the comment about the possibility of
some heaps being allocated out of the [uninitialized static data;bottom
of stack] range
and yes, of course continuity of allocated heaps is not guaranted
So isa looping is no more necessary unless you want to check ObjC
runtime structures more deeply (to track down a corruption, a
thrid-part framework behavior, )
Pascal Pochet
P3 Consulting
email@hidden
http://www.p3-consulting.net
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.