0

我正在编写一个框架,并且我有一个带有自定义 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我不确定这一点,内存管理是我生命中最重要的事情之一。

谢谢。

4

3 回答 3

6

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

-release,像在其他地方一样发送。即使在-init您不能保证当前保留计数为 1。


为什么你永远不能发送-dealloc除了[super dealloc]in -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则不会减少它。

于 2010-10-28T12:50:55.747 回答
2

根据文档,您永远不应该直接调用 dealloc - 只有[super dealloc]在您的自定义 dealloc 中的方法。

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

于 2010-10-28T12:35:07.067 回答
0

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

于 2010-10-29T03:35:28.943 回答