简体   繁体   English

Mac OS X 10.6中的NSOperation是否存在错误?

[英]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 . 如果在发送-init之前释放NSOperation实例, NSOperation出现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. Gnustep在其implementation of NSNumber做到了这一点,因此可以肯定的是,这也在Apple的代码中。 (At least was.) (至少是。)
  • NSObject s -init doesn't do anything, therefore -release , which belongs to NSObject should be working before that. NSObject-init不执行任何操作,因此,属于NSObject -release应该在此之前起作用。
// 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. 将除init以外的任何消息发送到尚未初始化的对象都是无效的代码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). 调用超类的初始值设定项,然后释放,我敢打赌它不会崩溃(尽管让一个类的初始值设定项返回一个完全不相关的类会令我感到doubleplusungood)。

There is nothing remotely valid about that code. 该代码没有远程有效的方法。

Rewrite your -init as: 将-init重写为:

- (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. 我认为您需要在调用release之前初始化您的超类,但是根据Apple文档中的此示例 ,情况并非如此。

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. 子类化NSObject没问题,但是例如,子类化NSOperation,NSOperationQueue和NSThread就是一个问题。

And it happens because just like YOU might do, the classes you subclass might allocate stuff in their -init method. 发生这种情况的原因是,就像您可能会做的那样,子类的类可能会在其-init方法中分配内容。 And that's also where you set to nil the variables you have not allocated yet (and might do so later in your code). 这也是您将未分配的变量设置为nil的地方(以后可能会在代码中这样做)。

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. 因此,通过不带-init情况下对自己调用-release ,可能会导致您的父类之一释放它尚未分配的对象。 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. 而且他们无法检查其对象是否为nil ,因为它甚至没有机会初始化所需的每个对象/值。

This also might be the reason why releasing NSOperation without init worked on 10.5 and doesn't work on 10.6. 这也可能是为什么在没有init的情况下释放NSOperation在10.5上有效而在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. 10.6实现已被重写为使用块和Grand Central Dispatch,因此,它们的initdealloc方法可能已发生很大变化,从而在那段代码上产生了不同的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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