4

自分のデータを入力してUIImageを作成しようとしています。これまでのところ、すべてが正常に機能しています。しかし、この関数を数回呼び出そうとすると、アプリがクラッシュするまでメモリがいっぱいになるようです。VM Trackerを使用すると、ダーティメモリが最大328MBに増加し、アプリがクラッシュしたときに290MBがCGイメージメモリであることがわかりました。

ARCが有効になっているループで関数を数回呼び出します。画像はかなり大きいですが、最初の29回の反復で正常に機能するため、問題にはなりません。私の知る限り、ダーティメモリはアプリケーションで再利用する必要があります。そうですか?では、なぜそれが私の記憶をいっぱいにするのでしょうか、そしてどうすればこの問題を回避できますか?

for(int i = 0; i < 1000; ++i) {
    UIImage *img = [self createDummyImage:CGSizeMake(2000, 1600)];
}

ダミーのUIImageを作成する関数:

- (UIImage*)createDummyImage:(CGSize)size
{
    unsigned char *rawData = (unsigned char*)malloc(size.width*size.height*4);

    // fill in rawData (logic to create checkerboard)

    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
    CGContextRef contextRef = CGBitmapContextCreate(rawData, size.width, size.height, 8, 4*size.width, colorSpaceRef, bitmapInfo);
    CGImageRef imageRef = CGBitmapContextCreateImage(contextRef);

    CGColorSpaceRelease(colorSpaceRef);
    CGContextRelease(contextRef);
    free(rawData);

    UIImage *image = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);

    return image;
}

hooleyhoopによる実用的なソリューション

関数呼び出しを自動解放プールに入れます。

for (int i = 0; i < 1000; ++i) {
    @autoreleasepool {
        UIImage *img = [self createDummyImage:CGSizeMake(2000, 1600)];
    }
}
4

1 に答える 1

5

Allocationsインストゥルメントの「ライブ」メモリを見ると、通常のメモリが不足していることがわかります。ダーティなVMとは関係ありません。

これは、自動解放されるのを待っているメモリが多すぎることが原因である可能性があります。自動解放されたオブジェクトは、現在の自動解放プールがポップされるまで解放されません。1つの自動解放プールに数百メガバイトのオブジェクトを追加しようとしています。

答えは、独自の自動解放プールを管理するか、1つのイベントループでそれほど多くの作業を行わないことです。

申し訳ありませんが、私はスナイドコメントに抵抗することはできません。私の意見では、これはARCの前にもっと明白だったでしょう。

于 2012-07-23T20:34:08.387 に答える