1

在目标 c 中,假设我有一个对象Obj存储在 NSMutableArray 中,并且指向它的数组指针是Obj整个程序中唯一的强指针。现在假设我调用一个方法Obj并在另一个线程中运行这个方法。在这种方法中,如果Obj将自身的指针设置为等于,nil它会本质上删除自己吗?(因为不会再有强指针了)我怀疑答案是否定的,但为什么呢?如果这确实有效,是不是不好的编码习惯(我认为它不是好的编码,但它实际上是坏的吗?)

4

4 回答 4

5

如果您的代码设计得当,一个对象极不可能导致其自己的释放/释放。所以是的,你描述的情况表明编码习惯不好,实际上可能导致程序崩溃。这是一个例子:

@interface Widget : NSObject
@property (retain) NSMutableArray *array;
@end

@implementation Widget

@synthesize array;

- (id)init
{
    self = [super init];
    if(self) {
        array = [[NSMutableArray alloc] init];
        [array addObject:self];
    }
    return self;
}

- (void)dealloc
{
    NSLog(@"Deallocating!");
    [array release];
    [super dealloc];
}

- (void)removeSelf
{
    NSLog(@"%d", [array count]);
    [array removeObject:self];
    NSLog(@"%d", [array count]);
}
@end

然后这段代码在另一个类中:

Widget *myWidget = [[Widget alloc] init];
[myWidget release];  // WHOOPS!
[myWidget removeSelf];

第二次调用 NSLog inremoveSelf将导致 EXC_BAD_ACCESS,因为此时array已被释放并且无法调用方法。

这里至少有几个错误。最终导致崩溃的一个事实是,创建和使用myWidget对象的任何类在使用它完成之前释放它(调用 removeSelf)。如果没有这个错误,代码将运行良好。但是,MyWidget 不应该有一个实例变量首先创建对自身的强引用,因为这会创建一个保留循环。myWidget如果有人在没有先调用的情况下尝试释放removeSelf,则不会释放任何内容,并且您可能会发生内存泄漏。

于 2012-06-01T20:50:41.093 回答
0

如果你的后向指针很弱(应该是因为一个类永远不应该尝试拥有它的所有者,你最终会得到一个保留循环)并且你从数组中删除了强指针,那么对象将从堆中删除. 没有强指针 = 从内存中删除。

您可以随时对此进行测试。

于 2012-06-01T20:20:06.797 回答
0

如果你需要一个类来解决它被删除的情况,最好的做法是首先保留/自动释放它,然后让这种情况发生。在这种情况下,类不会在其方法的中间被删除,而只会在之后被删除。

于 2012-06-01T20:21:09.147 回答
0

我认为我们可以说这可能是不好的编码习惯,这取决于你是如何做到的。您可以通过多种方式安全地或可能安全地进行操作。

所以让我们假设我们有一个全局:

NSMutableArray *GlobalStore;

一种方法是删除自己作为您的最终行动:

- (void) someMethod
{
   ...
   [GlobalStore removeObject:self];
}

由于这是最后的行动,因此应该没有未来的用途,self并且一切都应该很好,可能......

其他选项包括以 0 的时间延迟安排删除 - 这意味着它将在下一次运行循环周围触发(当然,只有当你有一个运行循环时才有效,而在线程中你可能没有)。这应该始终是安全的。

您还可以让一个对象保留对自身的引用,这会产生一个循环,从而使其保持活动状态。当它准备好死时,它可以取消自己的引用,如果没有其他引用并且这是一个最终操作(或另一个对象的计划操作),那么该对象就死了。

于 2012-06-01T22:25:32.550 回答