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

发布于 2024-08-06 03:56:46 字数 1028 浏览 2 评论 0原文

如果我在发送 -init 之前释放 NSOperation 实例,则会出现分段错误

我认为这是有效代码的原因:

  • Apple 在 其文档
  • Gnustep 在其 中执行此操作NSNumber 的实现,因此可以肯定这也在 Apple 的代码中。 (至少是。)
  • NSObject-init 不执行任何操作,因此 -release 属于 NSObject 应该在此之前工作。
// 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];
}
  • 你觉得怎么样,这是一个错误吗?
  • 您能给我展示另一个具有相同行为的类的示例吗?
  • 知道为什么会发生这种情况吗?

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.)
  • NSObjects -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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

何止钟意 2024-08-13 03:56:46

向尚未初始化的对象发送除 init 之外的任何消息都不是有效的代码 AFAIK。调用超类初始值设定项,然后释放,我打赌它不会崩溃(尽管让一个类的初始值设定项返回一个完全不相关的类让我觉得双重不好)。

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).

女中豪杰 2024-08-13 03:56:46

该代码没有任何远程有效的内容。

将你的-init重写为:

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

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

当然,代码仍然是废话,但它不会崩溃。

在向 self 发送消息之前,您必须始终调用 super 的初始化程序。并且您必须始终按照上面所示的模式进行操作。

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.

毁梦 2024-08-13 03:56:46

我认为您需要在调用发布之前初始化您的超类,但根据 Apple 文档中的此示例情况并非如此。

所以这可能是一个错误,但肯定不是一个重要的错误。

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.

标点 2024-08-13 03:56:46

我之前的分析并不完全正确。

但是,我想指出的是,这个问题可能会发生在不同的类中。这实际上取决于您要子类化哪个类。子类化 NSObject 没有问题,但子类化 NSOperation、NSOperationQueue 和 NSThread 等就是一个问题。

发生这种情况是因为就像您可能做的那样,您的子类可能会在其 -init 方法中分配内容。这也是您将尚未分配的变量设置为 nil 的地方(稍后可能会在代码中这样做)。

因此,通过在没有先前 -init 的情况下对自己调用 -release,您可能会导致您的父类之一释放它尚未分配的对象。他们无法检查他们的对象是否为nil,因为它甚至没有机会初始化它需要的每个对象/值。

这也可能是为什么在没有 init 的情况下发布 NSOperation 在 10.5 上有效但在 10.6 上不起作用的原因。 10.6 实现已被重写为使用块和 Grand Central Dispatch,因此,它们的 initdealloc 方法可能发生了很大变化,从而在该代码段上创建了不同的行为。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文