1

Cocoaプロジェクトでは、malloc/freeを使用する場所がたくさんありました。しかし、数か月前、ARCを活用するためにリファクタリングすることにしました。そのために、自動的にクリーンアップされるものへのポインターを返すmallocの代わりを作成しようとしました。

この機能を使用しました(エラーチェックやその他のログは省略)

+ (void *) MallocWithAutoCleanup: (size_t) size 
{
    NSMutableData * mutableData = [[NSMutableData alloc] initWithLength:size];
    void * data = [mutableData mutableBytes];
    return data;
}  

これはしばらくの間は正常に機能しましたが、最近、ランダムなメモリ上書きの問題が発生しました。この関数の原因を突き止めました。起こっているように見えるのは、mutableBytesへのポインターを保持しているにもかかわらず、NSMutableDataインスタンスの割り当てが解除されていることです。

これは、オブジェクトへの唯一の直接参照がローカルでなくなり、mutableBytesがオブジェクト内を指しているため、ARCがその種の参照カウントを処理するのに十分なほど賢くないために起こっていると思います。

mutableBytesポインターが使用されている(つまり、誰かがそれを参照している)限り、このコードをリファクタリングしてmutableDataオブジェクトを保持する方法はありますか?1つのオプションは、NSMutableData自体を返すことですが、これにはかなりのリファクタリングが必要であり、非常に面倒なようです。

4

2 に答える 2

9

10.7 SDK では、属性-[NSMutableData mutableBytes]で装飾されています。NS_RETURNS_INNER_POINTERこれは、メソッドがポインターを返すことをコンパイラーに知らせます。ポインターの有効性は、まだ存在するレシーバーに依存します。これに対して ARC が正確に何を行うかは変更の余地がありますが、現在はレシーバーを保持し、自動解放します (冗長な操作が最適化されていることを条件とします)。

したがって、ポインターは、現在の自動解放プールの存続期間中有効です。-[NSString UTF8String]これは(同じように装飾されている)に似ています。

ARC は、バイト ポインターへの参照がある限り、変更可能なデータ オブジェクトを存続させることができません。ARC はガベージ コレクターではありません。すべてのポインターのすべての使用を監視するわけではありません。現地で運営しています。これは、指定された 1 つの関数、メソッド、またはブロックを調べ、命名規則によって示されるコードの動作に対して保持および解放を発行します。(ARC は、ARC サポートでコンパイルされていないコードと相互運用できることに注意してください。)

avoid*はオブジェクト ポインターではなく、保持または解放できないため、ARC はそれに対して何もできません。したがって、メソッドを呼び出すコードでは-MallocWithAutoCleanup:、ARC は管理できるものを認識しません。特別なメモリ管理コードは発行しません。(その時点で何出力される可能性がありますか?) 呼び出し元をコンパイルしている間、コンパイラはメソッドの実装やその中の変更可能なデータ オブジェクトについて何も知らない可能性があります。

別の方法で考えてみてください。まだ手動で参照カウント コードを書いている場合、ポインターを有効に保つためにメソッドの呼び出し元で何をしますか? ほとんどの場合 (参照を無視し__weakて)、ARC が行うことはすべて、手動で行うことを自動的に行うことです。その場合、選択肢がないと考えると、ARCもそうではないことがわかります。

于 2012-05-31T21:41:00.777 に答える
2

あなたはあなた自身の質問に答えたと思います。NSData一般的なメモリ割り当てを管理するために使用する場合は、NSDataオブジェクトが所有するメモリを使い切るまで、オブジェクトへの参照を保持する必要があります。その時点で、問題の NSData オブジェクトへの参照を無効にします。これは、malloced メモリを手動で解放することに比べて利点がないようです。個人的には、ARC が malloc されたメモリを管理するような方法でコードをゆがめようとする代わりに、malloc()/free() を明示的に使用し続けます。

それか、そもそも malloc/free を使用する必要がないようにコードを記述します。典型的な「純粋な」Cocoa プロジェクトには、明示的な malloc() 呼び出しがあったとしてもそれほど多くはありません。正当な理由がない限り、呼び出しが行われたコードには少し疑いがあります。そもそも、なぜ malloc() を使用しているのですか?

于 2012-05-31T20:49:16.630 に答える