0

次のコードがあります。

UIImage *img = [UIImage imageNamed:@"BRBlueCircleMask"];
CGImageRef activeCirleMaskImage = img.CGImage;
activeCirleMaskLayer = [CALayer layer];
activeCirleMaskLayer.frame = CGRectMake(0, 0, 50, 50);
activeCirleMaskLayer.contents = CFBridgingRelease(activeCirleMaskImage);

EXEC_BAD_ACCESS は、2 行目で 70% の確率で発生します (つまり、正しく動作する場合もあります)。なにが問題ですか?

4

2 に答える 2

2

このコード スニペットからは問題は明らかではなく、イメージの読み込みに失敗した場合でも問題なく動作するはずです (イメージ リファレンスが NULL になるだけです)。

このように現れるメモリ管理の問題が別の場所にある可能性があります。または、デバッガーがクラッシュの場所について混乱している可能性があります。

于 2012-09-11T00:03:21.730 に答える
2

コードを次のように変更します (また、ARC を使用していると仮定しています)。まず、既存のコードにコメントを追加してから、問題を解決する方法を示します

// While this is a strong reference, ARC can release it after 'img.CGImage' (I have an accepted bug on this)
UIImage *img = [UIImage imageNamed:@"BRBlueCircleMask"];
// ARC should cause 
CGImageRef activeCirleMaskImage = img.CGImage;
 // you do not own the image, and a current ARC bug causes this object SOMETIMES to get released immediately after the assignment!!!
activeCirleMaskLayer = [CALayer layer];
activeCirleMaskLayer.frame = CGRectMake(0, 0, 50, 50);
activeCirleMaskLayer.contents = CFBridgingRelease(activeCirleMaskImage); // You are releasing an object here you don't own, which is the root cause of your problem

次のようにコードを変更します

UIImage *img = [UIImage imageNamed:@"BRBlueCircleMask"];
// want to get the CGImage copied ASAP
CGImageRef activeCirleMaskImage = CGImageCreateCopy(img.CGImage); // now you own a copy
activeCirleMaskLayer = [CALayer layer];
activeCirleMaskLayer.frame = CGRectMake(0, 0, 50, 50);
activeCirleMaskLayer.contents = CFBridgingRelease(activeCirleMaskImage); // OK now, its your copy

PS: CGImage の積極的なリリースが現実のものではないことを誰かが信じていない場合は、喜んでバグ レポートを投稿します (実際の問題を示すデモ プロジェクトと共に)。

編集: Apple はこれを修正しました。iOS6 にあったと思います。内部ポインタの使用を追跡し、そのポインタが範囲外になるまでメモリの解放を保留するようになりました。修正はSDKにあり、ヘッダーが定義されていたため、iOS6または7にリンクする必要があります-おそらくその展開ターゲットが必要かどうかもわかりません。

于 2012-09-11T11:29:09.000 に答える