1

アプリケーションで痕跡のない奇妙なクラッシュが発生しました。これはおそらくメモリ関連の問題ですが、情報がほとんどないため、続行または修正する方法がわかりません。楽器がなかったら、何の手がかりもなかったでしょう。

画像配列 (この例ではサイズ 2 の配列) があり、画像を読み込み、画像コンテキストを作成して描画し、配列に保存します。メソッドが呼び出されるたびに、画像配列オブジェクトが新しいコンテンツに置き換えられます。計測器では​​、このメソッドの呼び出し中に非常に大量の仮想メモリが使用されていることがわかります。明らかに、各呼び出しのメモリがクリアされていないため、クラッシュします。プロジェクトはARCです。以下にコードをリストします。この問題を再現するために必要なのはこれだけです。(私が使用しているイメージはサイズが約 7MB と少し大きいので、クラッシュを再現するのは簡単です)。また、私はiPad2デバイスを使用しています。

+ (UIImage *)imageCopy:(UIImage *)src
{
    UIGraphicsBeginImageContext(src.size);
    [src drawAtPoint:CGPointZero];
    UIImage *r = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return r;
} 

- (IBAction)buttonTouch:(id)sender
{
    for (int i=0; i<2; i++)
    {
        if (i==0)
        {
            self.mImage = [UIImage imageNamed:@"LARGE_elevation.jpg"];
        }
        else
        {
            self.mImage = [UIImage imageNamed:@"LARGE_elevation2.jpg"];
        }
        // imageArray is a NSMutableArray with capacity of 2
        [imageArray setObject:[ViewController imageCopy:self.mImage] atIndexedSubscript:i];
    }
    ((UIImageView *)[self.view viewWithTag:100]).image = self.mImage;
}

これは、メモリ警告が発行された後に 2 回目にクラッシュする計測器の画面です。

楽器のスクリーンショット

ここで使用している「imageCopy」メソッドに大きな問題はありません。

これに関するヘルプは本当に感謝しています。感謝と乾杯、

4

2 に答える 2

1

循環参照の問題であることがわかりました。そのため、配列内の古いコンテンツが新しいコンテンツに置き換えられると、過去のオブジェクトがまだ残っていました。メモリ リーク アナライザーでは、解放されていない仮想メモリが数百メガバイト (MB) であったため、疑うことのない数 KB のデータ リークが示されたため、これは非常に興味深い発見でした。

非常に抽象的な例として。

ClassA

@property (strong) ClassB *obj

----------

ClassB

@property (strong) ClassA *obj

- (id)initWithA:(ClassA *)objA;
----------

したがって、 A どちらのオブジェクトも削除すると、適切に割り当てが解除されます。私の場合、CoreGraphics の計算が仮想メモリ内の約 200MB のデータにかかっていたにもかかわらず、リーク アナライザーによってトレースされたリークは、両方のオブジェクトで数 KB でした。

修正は、ClassB の A 参照を弱いものとしてマークすることでした。

ClassB

@property (weak) ClassA *obj

- (id)initWithA:(ClassA *)objA;

評決

  • メモリ リークを過小評価することはありません。大小に関係なく & arc または mrc
于 2013-06-20T07:57:50.930 に答える