【问题标题】:Object not being deleted under ARC在 ARC 下未删除对象
【发布时间】:2012-01-31 12:44:10
【问题描述】:

当第二个对象被解除分配时,在第二个对象中创建的对象不会被解除分配,除非我在解除分配中将指针设置为 nil,这似乎不正确。

我认为 ARC 应该在对象被释放时默认将所有指针设置为 nil,从而释放所有拥有的对象。

这是我的代码(只是核心):

@interface Obj1 : NSObject
{
    Obj2 *obj2;   
}

@interface Obj2 : NSObject
{
}

@implementation Obj1

-(void)dealloc
{
    obj2 = nil;  // <--- This is needed to get obj2 to be dealloc'd.
    NSLog(@"Obj1 dealloc");
}

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

    obj2 = [[Obj2 alloc] init];

    return self;
}

@end

@implementation Obj2

-(void)dealloc
{
    NSLog(@"Obj2 dealloc");
}

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

    return self;
}

@end

我做错了吗?我读过的所有内容都说这应该有效。没有其他人持有 obj2 ,因为将其设置为 nil 会释放它。我已经尝试了带有和不带有 dealloc 函数的代码,以防万一它搞砸了,我得到了相同的结果。

有问题的文件正在编译为 obj-c++,但我没有对 c++ 和对象做任何事情。

谢谢。

【问题讨论】:

  • 好的,我找到了问题。我设置了启用僵尸对象。我很惊讶如果它没有设置为 nil,它会阻止对象被删除。我认为 Zombie Objects 只是在对象被删除后放置在该对象的位置上。如果它从不调用 dealloc,那可能会导致其他一些更大的问题。

标签: objective-c automatic-ref-counting objective-c++


【解决方案1】:

这绝对应该按照您期望的方式工作。您可能在您从示例中混淆或剪辑的代码中意外地做了一些事情。为了演示,您可以将下面的代码保存到某个文件中,例如arc_tst.m,编译它并从终端运行它。您会看到它打印出所有预期的日志语句,然后通过解除分配两个对象而结束。这些对象与您在此处发布的示例代码中的模型完全相同(证明问题很可能在您的实际代码的其他部分中)。

要编译它,假设你把它命名为arc_tst.m,切换到保存文件的目录,然后输入以下内容:

$ clang -fobjc-arc -o arc_tst arc_tst.m -framework foundation
$ ./arc_tst

arc_tst.m

// build with: clang -fobjc-arc -o arc_tst arc_tst.m -framework foundation

#import <Foundation/Foundation.h>

@class Obj1, Obj2;

@interface Obj1 : NSObject
{
  Obj2* _obj2;
}

@end

@interface Obj2 : NSObject
{
}

@end

@implementation Obj1

- (id)init
{
  if( (self = [super init]) )
  {
    _obj2 = [[Obj2 alloc] init];
  }
  return self;
}

- (void)dealloc
{
  NSLog(@"Obj1 Dealloc");
}

@end

@implementation Obj2

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

- (void)dealloc
{
  NSLog(@"Obj2 Dealloc");
}

@end

int main (int argc, char const *argv[])
{
 @autoreleasepool {
  Obj1* obj = [[Obj1 alloc] init];
  NSLog(@"after alloc, have obj1: %@", obj);
  sleep(2);
  NSLog(@"after sleep, have obj1: %@", obj);
  obj = nil; // force ARC to trash obj
  NSLog(@"after nil on obj1, about to exit");
 }
 return 0;
}

【讨论】:

  • 您的代码示例按照您的描述工作。我只是不知道我在我的代码中做了什么。我的 Obj1 正在被释放,但除非我将 Obj2 设置为 nil,否则它不会。我正在将我的代码编译为 obj-c++,我不知道这是否会有所不同。
  • @RogerGilbrat 嗯......这很可能会有所作为。我在问题中添加了标签,但您可能希望更新您的问题,以更准确地说明您如何使用此代码以及它如何与 C++ 代码交互。
  • 它根本不与 c++ 代码交互。我使用 c++ 的唯一目的是能够基于参数类型重载纯 c 函数。而已。没有被删除的对象对 c++ 没有任何作用。所有这些都是纯 obj-c。
  • @RogerGilbrat 这很奇怪。 Clang 实际上支持 C++,例如在不使用 C++ 的情况下重载 C 函数。您可能想检查一下,看看它是否修复了它? clang.llvm.org/docs/LanguageExtensions.html#overloading-in-c
  • 哦,这很有用。感谢您的提示。
猜你喜欢
  • 1970-01-01
  • 2023-03-19
  • 2012-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-10
  • 1970-01-01
  • 2020-03-18
相关资源
最近更新 更多