0

NSOperation如果我在发送给它之前释放一个实例,-init我会得到一个segmentation fault.

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

  • Apple 在其文档中做到了这一点。
  • Gnustep 是在它implementation of NSNumber的 . (至少是。)
  • NSObjects-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];
}
  • 你怎么看,这是一个错误吗?
  • 你能告诉我另一个具有相同行为的类的例子吗?
  • 知道为什么会这样吗?
4

4 回答 4

7

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

于 2009-10-04T18:38:21.390 回答
2

该代码没有任何远程有效。

将您的 -init 重写为:

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

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

当然,代码仍然是胡说八道,但它不会崩溃。

在向 self 发送消息之前,您必须始终调用 super 的初始化程序。而且您必须始终使用上面显示的模式。

于 2009-10-04T18:46:32.380 回答
1

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

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

于 2009-10-04T18:47:32.067 回答
1

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

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

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

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

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

于 2009-10-04T19:45:37.237 回答