Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Callstack is deallocated before an NSException in autorelease pool #82

Open
sidslog opened this issue Dec 29, 2014 · 3 comments
Open

Callstack is deallocated before an NSException in autorelease pool #82

sidslog opened this issue Dec 29, 2014 · 3 comments

Comments

@sidslog
Copy link

sidslog commented Dec 29, 2014

When you have an autorelease pool and throw and catch an exception inside, the "reserved" ivar (that contains callstack) of an NSException is deallocated before the instance of NSException.

To reproduce the crash

@autoreleasepool {
    @try{
        @throw [NSException exceptionWithName:@"1" reason:@"2" userInfo:nil];
    }
    @catch (NSException *e) {
    }
}

This is how it looks in the debugger

#0  0x000b082b in handleDealloc at /Users/sidslog/projects/TestException/KSCrash/Source/KSCrash/Recording/Tools/KSZombie.m:149
#1  0x000b07a6 in -[NSObject(KSZombie) dealloc_KSZombieOrig] at /Users/sidslog/projects/TestException/KSCrash/Source/KSCrash/Recording/Tools/KSZombie.m:167
#2  0x00421f18 in -[_NSCallStackArray dealloc] ()
#3  0x0083f772 in objc_object::sidetable_release(bool) ()
#4  0x00840a63 in -[NSObject release] ()
#5  0x00b28c37 in CFRelease ()
#6  0x00b5debe in -[__NSDictionaryM dealloc] ()
#7  0x0083f772 in objc_object::sidetable_release(bool) ()
#8  0x00840a63 in -[NSObject release] ()
#9  0x00c686ec in -[NSException dealloc] ()
#10 0x0083f772 in objc_object::sidetable_release(bool) ()
#11 0x0083ee9b in objc_release ()
#12 0x0083fd32 in (anonymous namespace)::AutoreleasePoolPage::pop(void*) ()

At first it deallocates the callstack then an ivar and only after that an instance of NSException.
When handling the deallocation of an NSException in storeException, there is no "reserved" ivar. So the EXC_BAD_ACCESS happens at line

NSArray* callStack = [exception callStackReturnAddresses];

At my point of view, there is a way to handle this crash - to swizzle the "release" method of NSExcepsion instead of "dealloc". Then the chain of releasing would look like this: NSException -> "reserver" ivar -> callstack. But I haven't tested a lot(

@jianjingbao
Copy link

I also has similar bug, who has solution?

Application Specific Information:
*** Terminating app due to uncaught exception  NSInvalidArgumentException , reason:  -[__NSMallocBlock__ objectForKey:]: unrecognized selector sent to instance 0x179b86c0 

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   CoreFoundation                  0x2b41a49f __exceptionPreprocess + 127
1   libobjc.A.dylib                 0x38c31c8b objc_exception_throw + 39
2   CoreFoundation                  0x2b41f8b9 __methodDescriptionForSelector + 1
3   CoreFoundation                  0x2b41d7d7 ___forwarding___ + 715
4   CoreFoundation                  0x2b34f058 __forwarding_prep_0___ + 24
5   MTMessage                       0x003403f1 0xdd000 + 2503665 (-[NSObject(KSZombie) dealloc_KSZombieOrig] + 233)
6   CoreFoundation                  0x2b41a2f7 -[NSException dealloc] + 135
7   libobjc.A.dylib                 0x38c4bd5f objc_object::sidetable_release() + 167
8   libobjc.A.dylib                 0x38c4c1a9 (anonymous namespace)::AutoreleasePoolPage::pop() + 405

}

@sidslog
Copy link
Author

sidslog commented Jun 30, 2015

This happens only if you trace zombies with KSCrash. So our workaround is to set zombieCacheSize to zero

@yvasileuski
Copy link

more discussion here #155

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants