web-dev-qa-db-ja.com

オブジェクトは解放された後に変更された可能性があります

私はiPhoneでプロジェクトに取り組んでいます。別のUIViewControllerから新しいUIViewControllerを開始し、それらを切り替えています。これが私のコードです。

iGreenAppDelegate *delegate = [UIApplication sharedApplication].delegate;
if(checkInViewController) {
    [checkInViewController release];
    checkInViewController = nil;
}
checkInViewController = [[CheckInViewController alloc] initWithCheckpoint:checkpoint];

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.8];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:[delegate window] cache:YES];
[[delegate rootTabBarController].view removeFromSuperview];
[[delegate window] addSubview:checkInViewController.view];
[UIView commitAnimations];

問題は、UIViewControllerを2回目に起動するときに発生し、メモリリークの発生を回避するために解放したいと思います。デバッガが表示されます

iGreen(916,0x3f60348c)malloc:オブジェクト0x130350のエラー:解放されたオブジェクトの不正なチェックサム-オブジェクトは解放された後に変更された可能性があります。 malloc_error_breakにブレークポイントを設定してデバッグする

他の部分の同様のコードはそのようなエラーを返さないので、これは奇妙です。さらに、自動解放を試みましたが、プログラムはすぐにクラッシュし、デバッガーはファイナライズされたレイヤーを変更していると言っています。

私は一晩中この問題に取り組んできましたが、それでも混乱しました。

16
Stone

デバッグするmalloc_error_breakにブレークポイントを設定します。

それを行い、バックトレースを投稿します。

通常、これはメモリが破損していることを意味しますが、オブジェクトが過剰に解放されている可能性もあります。ビルドと分析もお試しください。

18
bbum

Malloc_error_breakにブレークポイントを設定する以外に、xCodeでCommand-6を押して、ブレークポイントタブにジャンプします。また、スキームでmallocエイドを有効にします。

スキームセレクターに移動し、「スキームの編集」を選択して「実行」ターゲットを見つけ、「診断」タブに移動します。メモリ管理の下では、落書き、ガードエッジ、ガードmalloc、ゾンビオブジェクトを有効にします。

少し運がよければ、xCodeは割り当てられたメモリの外側で書き込みを行ったり、メモリを破壊したりします。

それは、記憶を扱うための大人の監督のようなものです...

9
Niels Castle

エラーメッセージを理解します。解放した後も、何かがオブジェクトの使用(および変更)を継続しているということです。このコードはそれを解放し、その後それを変更しませんが、(すでに解放されていることを知らずに)他に何がそれを使い続けることができるかを尋ねる必要があります。

このスニペットのコードが実行されるたびに、既存のcheckinViewControllerが解放(解放)され、新しいコードが割り当てられます。明らかに、古いコードに再度触れることはありません。しかし、他に誰が古いオブジェクトへのポインタを持っているのでしょうか?

おそらくあなたが書いた他のコード、そしておそらく[デリゲートウィンドウ]が "[[デリゲートウィンドウ] addSubview:checkInViewController.view];"を介して参照を取得しますか?うまくいけば、後者は独自の参照を取得します。つまり、リリースによってすぐには解放されません。

ただし、参照を追加せずにそのポインタをコピーしている場所には注意してください。これをどこかで行ってから、別の場所(上記のスニペットなど)で同じポインターに対して誰かがreleaseを呼び出した場合、解放されたオブジェクトへのポインターを持っている可能性があります。

3
metamatt

コードの設計がうまくいかないことがいくつかあります。最初に、スーパービュー(存在する場合)からビューを削除せずにcheckInViewControllerを解放してから、スーパービューからrootTabBarControllerのビューを削除します。コントローラー自体には何も実行せず、rootTabBarControllerまたはrootViewControllerプロパティにcheckInViewControllerを追加しません。ウィンドウの空中です(現在のオブジェクトに保持されているだけです)。この(現在の)オブジェクトの割り当てが解除されたが、checkInViewControllerのビューがウィンドウに配置(保持)されたままの場合はどうなりますか?

CheckInViewControllerを解放しても、そのビューがウィンドウによって保持されている場合、おそらくいくつかの問題が発生します...

エラーについては、解放された後にそれに作用するオブジェクトへの弱い参照(保持されていない)がどこかにあると思います。

1
tsakoyan