简体   繁体   中英

Is there a bug in NSOperation in Mac OS X 10.6?

If I release an instance of NSOperation before sending -init to it I get a segmentation fault .

Reasons I think this is valid code:

  • Apple does this in its documentation .
  • Gnustep does it in its implementation of NSNumber , so it's fairly certain that this is in Apple's code too. (At least was.)
  • NSObject s -init doesn't do anything, therefore -release , which belongs to NSObject should be working before that.
// gcc -o test -L/System/Library/Frameworks -framework Foundation test.m

#import <Foundation/Foundation.h>

int main(int argc, char *argv[]) {
    NSOperation *theOperation = [NSOperation alloc];
    [theOperation release];
}
  • What do you think, is this a bug?
  • Can you show me an example of another class that has the same behavior?
  • Any idea why this is happening?

Sending any message other than init to an object that has not been initialized is not valid code AFAIK. Call the superclass initializer and then release and I'm betting it won't crash (although having one class's initializer return a completely unrelated class strikes me as doubleplusungood).

There is nothing remotely valid about that code.

Rewrite your -init as:

- (id) init
{
    if (self = [super init]) {
        [self release];

        NSNumber *number = [[NSNumber alloc] initWithInteger:6];
        return number;
    }
    return self;
}

Of course, the code is still nonsense, but it doesn't crash.

You must always call through to the super's initializer before messaging self. And you must always do it with the pattern shown above.

I thought you need to initialize your superclass before calling release, but according to this example in Apple's docs that's not the case.

So it may be a bug, but certainly not an important one.

My previou analysis was not really correct.

However, I want to point that this issue can happen with different classes. It actually depends on which class you're subclassing. Subclassing NSObject is no problem, but subclassing NSOperation, NSOperationQueue, and NSThread is an issue, for example.

And it happens because just like YOU might do, the classes you subclass might allocate stuff in their -init method. And that's also where you set to nil the variables you have not allocated yet (and might do so later in your code).

So, by calling -release on yourself without a previous -init , you might cause one of your parent classes to release object that it had not allocated. And they can't check if their object is nil , because it didn't even have the opportunity to init every object/value it needs.

This also might be the reason why releasing NSOperation without init worked on 10.5 and doesn't work on 10.6. The 10.6 implementation have been rewritten to use blocks and Grand Central Dispatch, and thus, their init and dealloc methods might have changed greatly, creating a different behavior on that piece of code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM