1

自動参照カウントを使用して記述されたアプリケーションで、異なる NSImage を繰り返しロードするときに問題が発生しました。ARC が画像オブジェクトを正しく解放していないように見えます。代わりに、反復が完了するまでリストが反復されるにつれてメモリ使用量が増加し、その時点でメモリが解放されます。

場合によっては、プロセス全体で最大 2 GB のメモリが使用されています。プロセスを NSAutoReleasePool に入れ、イメージを解放してプールを空にする非常によく似た問題について、SO に関する良い議論があります。これは、ARC を使用しない場合でも機能しますが、ARC でこれらのオブジェクト/メソッドを呼び出すことはできません。

これをARCでも機能させる方法はありますか?ARC はこれをすべて自分で考え出す必要があるようです。これらのオブジェクトがリリースされないという事実は、OS X のバグに違いないと思います (私は XCode 4.2.1 で Lion を実行しています)。

問題の原因となっているコードの種類は次のようになります。

+(BOOL)checkImage:(NSURL *)imageURL
{
    NSImage *img = [[NSImage alloc] initWithContentsOfURL:imageURL];
    if (!img)
         return NO;

    // Do some processing
    return YES;
}

このメソッドは、ループ内で繰り返し呼び出されます (たとえば、300 回)。アプリのプロファイリングでは、各画像に割り当てられた 7.5MB でメモリ使用量が増加し続けています。ARC を使用しない場合は、次のことを実行できます (このトピックで提案されているように)。

+(BOOL)checkImage:(NSURL *)imageURL
{
    NSAutoReleasePool *apool = [[NSAutoReleasePool alloc] init];
    NSImage *img = [[NSImage alloc] initWithContentsOfURL:imageURL];
    if (!img)
         return NO;

    // Do some processing

    [img release];
    [apool drain];

    return YES;
}

ARCにメモリクリーニングを強制する方法を知っている人はいますか? とりあえず、コンパイラフラグとして渡された -fno-objc-arc でコンパイルされたファイルに関数を入れました。これは問題なく動作しますが、ARC にそれをしてもらうとよいでしょう。

4

1 に答える 1

3

@autoreleasepool次のように使用します。

+(BOOL)checkImage:(NSURL *)imageURL
{
    @autoreleasepool { // << push a new pool on the autotrelease pool stack
      NSImage *img = [[NSImage alloc] initWithContentsOfURL:imageURL];
      if (!img) {
         return NO;
      }
      // Do some processing
    } // << pushed pool popped at scope exit
    return YES;
}
于 2012-08-21T13:39:13.847 に答える