我正在编写一个框架,我有一个带有自定义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
?我不确定这一点,记忆管理是我生命中最重要的事情之一。
感谢。
答案 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
。