NSOperationQueue NSOperation USER_INITIATED crash

733 views Asked by At

I'm using NSOperation and NSOperationQueue in my application. When encounter below warning with EXC_BAD_ACCESS crash, where should I start to debug? I just google it, and didn't find the answer.

enter image description here

Add more information, here is the screenshot of the Debug Navigator enter image description here

Does it mean that it crashed when releasing something?

UPDATE

I just enabled Zombie Objects and get below information

*** -[AFJSONResponseSerializer release]: message sent to deallocated instance 0x7fdfb378b550

Add more information, I'm not using ARC in my application. For AFNetwork library, I added -fobjc-arc for each *.m file in AFNetwork.

I wonder:

  1. According to some answers on stackoverflow I found before, I did not add @autoreleasepool for each NSOperation, am I right?
  2. Do I also need add -fobjc-arc for each *NSOperation.m I implemented in my application?
  3. is it a known issue of AFNetwork?
1

There are 1 answers

0
iAdjunct On

If you're seeing objc_release as the culprit, then it's trying to release something that's:

  • Already been deallocated
  • Not a [valid] object

(OR your stack has been corrupted so far that it's calling the wrong functions, but this isn't all that likely).

Firstly, expand the ...... and see if it shows anything useful (there's a slider somewhere to show more detail).

Secondly, as a stylistic standpoint, you might want to more directly use blocks instead of NSOperation. Then you can use either

  • -[NSOperationQueue addOperationWithBlock:]
  • dispatch_async ( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT) , ^{ ... } ) ;

Barring that for the moment, you still need to debug this.

Are you using ARC? If so, this is almost definitely related to a line like one of these:

// This keeps an unretained Objective-C pointer. Later, if you
// try to use it, it may retain it and release it.
__unsafe_unretained id object = someObjectiveCObject ;

// This bridges the object, but doesn't retain it. If you
// bridge it back later, it'll try to release it at the end,
// but you never owned it.
CFTypeRef object = (__bridge CFTypeRef) someObjectiveCObject ;
id later = (__bridge_transfer id) object ;

// This uses an uninitialized pointer
CFTypeRef object ;
dispatch_async ( dispatch_get_main_queue() , ^{
    id object = (__bridge_transfer id) object ;
} ) ;

If not, why aren't you? In this case, you'll have to scour your code to find where you didn't retain something.

I strongly suggest running Xcode's static analyzer and looking very carefully at every thing it highlights - it's really good at spotting these issues since it knows about ownership and transfers thereof.

UPDATE

Since you're not using ARC, things may be harder to find because now the pool of possible issues is larger. Hopefully there aren't many of those classes being allocated.

What I'd recommend is modifying the code to that class add these:

- (id) retain {
    return [super retain] ;
}
- (void) release {
    [super release] ;
}

Then put breakpoints on those (plus their initializers and dealloc method) and see where they get called. Then trace that object to find a place you think it doesn't own it but it's still calling -release on it.

The static analyzer is your friend here: use it too.