在init中调用dealloc?

时间:2010-10-28 12:31:25

标签: objective-c dealloc init nsobject

我正在编写一个框架,我有一个带有自定义init方法的对象:

@implementation OSDatabase
@synthesize database;

// MEM
- (void)dealloc {
  sqlite3_close(database);

  [super dealloc];
}

// INIT
- (id)initWithDatabasePath:(NSString *)path error:(NSError **)error {
  if (self = [super init]) {
    if (!sqlite3_open_v2([path UTF8String], &database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)) {
      error = [NSError errorWithDomain:@"OSDatabaseErrorDomain" code:1 userInfo:nil];
      [self dealloc];
      return nil;
    }
  }

  return self;
}

@end

如果出现错误,是否可以安全地在dealloc方法中调用init?我不确定这一点,记忆管理是我生命中最重要的事情之一。

感谢。

3 个答案:

答案 0 :(得分:6)

  

如果出现错误,在init方法中调用dealloc是否安全?

没有。像其他地方一样发送-release。即使在-init中,也无法保证当前的保留计数为1。


为什么你永远不能在-dealloc中发送除[super dealloc]之外的-dealloc?原因是您无法保证其他内容也会引用您的对象,即使在对象的-init中也是如此,因为[super init]可能会选择保留该对象。

如果[super init]返回的对象的保留计数为1,则发送-release与发送-dealloc的效果相同。如果它的保留计数大于1,那么其他东西认为它拥有该对象并释放它会使它带有无效指针,因此-release仍然是正确的事情。

另外,这个:

while([self retainCount] != 0){[self release];}
由于种种原因,

会导致无限循环并且是一个糟糕的主意。对象的保留计数永远不会降至0. -release看起来像这样:

- (id)release
{
    if (retainCount == 1)
    {
        [self dealloc];
    }
    else
    {
        retainCount--;
    }
}

所以循环会将保留计数减少到1,然后永久地调用dealloc,或者直到它导致的堆损坏导致seg错误。

除了永远不会达到零之外,保留可能是UINT_MAX(例如在字符串或数字文字中),通俗地表示“此对象永远不能被释放”。如果保留计数为UINT_MAX-release将不会减少它。

答案 1 :(得分:2)

每个文档你永远不应该直接调用dealloc - 只有你自定义dealloc中的[super dealloc]方法。

我认为调用release代替应该做的事情(至少如果你只在标准的alloc-init模式中使用init方法)。

答案 2 :(得分:0)

正如弗拉基米尔所说,你不应该直接打电话给dealloc。当一个对象的保留计数达到0时,Cocoa会自动调用dealloc