2

malloc()Objective-Cでは、( Cのように)メモリ割り当てを担当する方法はです-[NSObject alloc]。そのメモリを解放するのはどうですか?それはによって行われ-[NSObject dealloc]ますか?そのため、私たち自身のクラスでは、最初ではなく最後にdealloc呼び出す必要がありますか?[super dealloc]

理由がわからないので、[super dealloc]最初に置いて次の行でオブジェクトを解放して[_bar release]も、セグメンテーション違反が発生しないので質問します。実行後[super dealloc]、オブジェクトのメモリを解放する場合は_bar、プロセスに属していないメモリチャンクである必要があります。

4

4 に答える 4

6

私はあなたが言っていると思います、あなたはこのコードを持っています:

- (void)dealloc
{
    [super dealloc];
    [_bar release]; // _bar is a member variable
}

また、2行目でセグメンテーション違反が発生することが予想されますが、実際にはそうではありません。

この理由は運です!

OSは、プロセスが所有していないメモリへのアクセスをトラップしますが、プロセス内で発生するすべてを監視するわけではありません。この場合、空きとしてマークしたメモリにアクセスしていますが、それでもプロセスに属しているため、動作は未定義です。メモリは数ミリ秒前に有効であったため、このページのメモリの再利用をまだ開始していない可能性があります。したがって、おそらくまだ有効なデータが残っています。だからそれは成功するかもしれません。しかし、それも失敗する可能性があります。

これは悪いコードであり、出荷すべきではありません。しかし、それが正しくなく、未定義であるからといって、それが機能しないという意味ではありません。

于 2012-09-11T17:36:26.040 に答える
1

最も単純な「概念的な」ケースでは、deallocNSObjectのルーチンが操作を実行し、ルーチンで実行されたものfreeをミラーリングします。実際には異なる場合がありますが、概念モデルが満たされている限り、それはすべて煙と鏡です。mallocalloc

[super dealloc](ARC以前の)ルーチンを最初に配置した場合dealloc、スペースは解放されている間、他のオブジェクトによって上書きされる時間がないため、ほとんどの場合、セグメンテーション違反は発生しません(また、割り当てを解除しても物理的に消えることはありません- 「利用可能な」リストに入るだけです)。

于 2012-09-11T17:36:52.280 に答える
1

-dealloc最終的に、Objective-Cオブジェクトに関連付けられたメモリを解放します(おそらく、を介してfree()、しかしそれは実装の詳細です)。後でメッセージを送信できる唯一の理由-deallocは、未定義の動作のためです。[super dealloc]が送信された後、selfまたはそのivarへのそれ以降のメッセージは安全ではありません。

于 2012-09-11T17:26:36.710 に答える
1

はい、alloc割り当てが行われる場所です。実行される場合とされない場合があり、割り当てがまったくない場合もあることに注意してください(これは実装の詳細です)。割り当ては通常、のNSObject実装で行われallocます。

メモリが割り当てられている場合、への連鎖呼び出しdeallocは最終的にそれを解放するものです。

を呼び出した後、インスタンス変数にアクセスすることは想定されていません[super dealloc]。これは、セグメンテーション違反が発生したことを意味するものではありません。セグメンテーション違反の場合もそうでない場合もありますが、これは未定義の動作です。

ただし、覚えておくべき重要なことは、dealloc実装自体での呼び出しを除いて、直接呼び出すべきではないということです。ObjectiveCは参照カウントです。あなたがオブジェクトを使い終わったとき、あなたはそれをしません。代わりにあなたはそれをします(またはあなたが終わったがあなたはそれを発信者に返していて、発信者がそれを使うかどうかわからない場合)。実際の呼び出しは、システムがそのオブジェクトを参照する人がもういないことを確認したときに自動的に行われます。dealloc[super dealloc]deallocreleaseautoreleasedealloc

編集:

割り当てがまったくない場合があることを明確にします。実際、allocを呼び出すと、通常、割り当てが発生しますが、init*メソッドによって元に戻される場合があります。原則として、へのすべての呼び出しのalloc直後に、初期化子の1つへの呼び出しが続く必要があります。ただし、初期化子は、受信した初期化子を初期化する必要はありませんself。代わりに、それを取り除き(したがって、メモリを解放し)、完全に異なるオブジェクトを返すことができます。これは、割り当てられている場合とされていない場合があります。

したがって、その場合、によって割り当てられたメモリallocは、実際には初期化子によって解放されます(それを実行するために呼び出す場合と呼び出さない場合がありますdealloc)。また、初期化後に取得するオブジェクトは、ヒープに割り当てられておらず、解放されることのない静的オブジェクトである可能性があります。(void*)また、 (別名id)にキャストされて返される非ポインター(無効なアドレス)である可能性もあります。

于 2012-09-11T17:41:32.390 に答える