0

質問が 2 つありますが、まず、単純さゆえに明らかに混乱しやすい質問から始めましょう。

-(void)OnNewFrameData:(NSData *)FrameData 
{
    UIImage * I = [UIImage imageWithData:FrameData];
    [I release];
}

を解放しないIと、メモリ リークが発生します。それでも、私は決して保持しませんでしたI。誰かがこれを説明できますか?(FrameData呼び出し元によって完全に管理されます。)

次に、保持されたプロパティについて別の質問があります。上記の同じコードIを取得し、保持されたプロパティJに割り当ててから、同じ保持されたプロパティに nil を割り当てます。リークは発生しないはずですが、再びメモリリークが発生しています。保持されたプロパティも解放できますが、それでもリークが発生します。

@property (retain) UIImage * J;

...

-(void)OnNewFrameData:(NSData *)FrameData 
{
    UIImage * I = [UIImage imageWithData:FrameData];
    self.J = I;
    // I can also add here [self.J release]; and it still leaks...
    self.J = nil;
    [I release];
}

ドキュメントとスタックオーバーフローのスレッドの両方から学んだことから、これら 2 つの紛らわしい明らかな矛盾についての洞察をいただければ幸いです。

4

2 に答える 2

-1

そこで、次のコードで実験してみました...

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    UIImage * Img = [[UIImage imageWithData:FrameData] retain];
    [pool drain];

    int n = [Img retainCount];

上記のコードでは、Imgの保持カウントが1に戻ります。自動解放プールを削除すると、2になります。これは、imageWithData:が自動解放されたオブジェクトを返すことの完全な証拠であり、これはまさに私たち全員が期待することです。

したがって、私の唯一の結論は、プールがImgをすぐにリリースしておらず、連続する各イメージがネットワークを介してプールされていたということです。最終的に私はメモリを使い果たしました。

元の問題の最初の部分について他に誰も考えがない場合、私はこれを答えとして使用する必要があります。

私はまだ2番目の問題に関して手がかりがありません。

アップデート:

これまでずっと私を混乱させていたのは、自動解放のフラグが立てられたメインスレッド上のオブジェクトがどのようにしてタイムリーに解放されるのかということです。自動解放は、メモリプールのメモリが不足するたびに動作するガベージコレクタのようなものだといつも思っていました。しかし、文献を振り返ると、GBは、GB以外の環境で使用できるため、自動リリースプールの目的ではないことは明らかです。自動解放プールは、ドレインメッセージによってプールが破棄されるまで、オブジェクトを解放しません。

では、メインスレッドオブジェクトはどうですか?プログラムが終了するまで蓄積されないのはなぜですか?フレームワークがクラ​​スオブジェクトの1つを呼び出すたびに(更新:イベントをディスパッチするたびにコードを呼び出すフレームワークについて話している)、最初に新しいを設定するため(ここで推測しますが、これが最も論理的な説明です)自動解放プール。したがって、フレームワークによって作成されたクラスオブジェクトの1つに対するメソッド呼び出しのすべてのオブジェクトは、新しいプールに囲まれ、フレームワークがコードから制御を受け取ると、自動解放のフラグが付けられたすべてのオブジェクトが解放されます。

誰かがこれにもっと光を当てるための情報を持っているなら、私はあなたから聞いてみたいです。

于 2012-08-16T22:24:00.517 に答える
-1

[UIImage imageWithData]以下のような便利なメソッドです。

-(UIImage*)imageWithData:(NSData*)data{
   UIImage *img = [[UIImage alloc] initWithData:data];
   [img autorelease];

   return img;
}

ご覧のとおり、保持カウントを 1 に設定する割り当てがあります。これが明確になることを願っています。さらに明確にすることができれば、コメントを残してください。イメージを自動解放プールに配置するように求められました。プールのドレイン後にイメージを保持する場合は、作成時に保持する必要があります。

正しい方法は、使用することです。

 [[UIImage imageWithdata:data]retain];

これを行うと、保持カウントが 2 になり、プールのドレイン時に 1 減少します。したがって、必要なリリースは 1 つだけです。

ps アナライザーを実行することもできます。メモリの問題を指摘します。(CMD + シフト + b)

別の考え。i が nil でないことを確認できますか。ドキュメントによると、UIImage の作成に失敗した場合は nil が返されるため、問題が発生する可能性があります。

于 2012-08-16T07:24:11.093 に答える