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これについてはよくわかりませんが、メモリ管理は私の人生で最も重要なことの 1 つです。

ありがとう。

4

3 に答える 3

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 を永久に、またはそれによって引き起こされたヒープの破損がセグ フォールトにつながるまで継続的に呼び出します。

決してゼロにならないこととは別に、retain は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 に答える