*クラッシュがクラッシュしていないという単純なObjective-Cの過剰リリース。なんで?

StackOverflow https://stackoverflow.com/questions/4079198

質問

私のデバッガーが壊れているか、私が理解していない基本的な何かがあります。

私は非常に基本的なコマンドラインプログラムにいくつかの非常に基本的なコードを持っています したほうがいい クラッシュ。ただし、クラッシュしていません。

int main (int argc, const char * argv[])
{
    NSString *string = [[NSString alloc] initWithString:@"Hello"];

    [string release];

    NSLog(@"Length: %d", [string length]);

    return 0;
}

ログステートメントは、有効な文字列に期待されるように、「長さ:5」を印刷します。ただし、文字列はその時点で扱う必要があり、 exec_bad_access エラーをスローする必要があります。

デバッガーが添付された状態でこのコードを試しましたが、デバッガーが添付されていません。どちらも同じ結果をもたらしました。私も有効にしています(そして無効にしています) NSZombie, 、それは効果がないようです(私は最初、これが問題だと思っていました。 NSZombie オブジェクトは決して扱われることはありませんが、それでもクラッシュしません NSZombie 無効)。

地元のブレークポイントが設定されています .gdbinit などを破るファイル -[NSException raise]objc_exception_throw. 。また、多くの方法でブレークポイントが設定されています NSZombie それらを捕まえるために。

fb -[NSException raise]
fb -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:]
fb -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]

#define NSZombies
# this will give you help messages.  Set to NO to turn them off.
set env MallocHelp=YES
# might also be set in launch arguments.
set env NSZombieEnabled=YES
set env NSDeallocateZombies=NO
set env MallocCheckHeapEach=100000
set env MallocCheckHeapStart=100000
set env MallocScribble=YES
set env MallocGuardEdges=YES
set env MallocCheckHeapAbort=1

set env CFZombie 5

fb -[_NSZombie init]
fb -[_NSZombie retainCount]
fb -[_NSZombie retain]
fb -[_NSZombie release]
fb -[_NSZombie autorelease]
fb -[_NSZombie methodSignatureForSelector:]
fb -[_NSZombie respondsToSelector:]
fb -[_NSZombie forwardInvocation:]
fb -[_NSZombie class]
fb -[_NSZombie dealloc]

fb szone_error
fb objc_exception_throw

これらのブレークポイントが設定され、nszombieが有効になっていると、次のようなものを手に入れる必要があります [NSString length]: message sent to deallocated instance 0x100010d39 コンソールに印刷されましたが、私はこれを見ません。私は見ます NSLog 長さを5として印刷します。

などの他のクラスと同様の動作が見られます NSURLNSNumber. 。しかし、一部のクラスは、予想どおりクラッシュします NSErrorNSObject.

これはクラスクラスターと関係がありますか?彼らはメモリ管理に関して同じルールに従っていませんか?

クラスクラスターがこの問題に関連していない場合、私が見ることができる他の一般的な機能は、このようにクラッシュしないクラスがすべてコアファンデーションのカウンターパートで架かるフリーフリーであるということでした。これはそれと関係があるでしょうか?

役に立ちましたか?

解決

retain/release APIとプログラマーの間の契約であり、ルールに従うとクラッシュしないという契約です。契約は、ルールに従わない場合、クラッシュすることを保証しません!

この場合、

[[NSString alloc] initWithString:@"Hello"]

同じオブジェクトを返すだけです @"Hello" 最適化として。定数 NSString 決して取り引きされません。最適化として、 retainrelease (私は思う)無視されています。それがクラッシュしない理由です。

のポインター値を比較することで、私の推測を確認できます @"Hello"string.

他のヒント

これは、なぜ保持カウントがかなり役に立たないデバッグツールである理由の優れた例です。 -retainと-releaseが常に保持数から1を追加または削除すると想定するのは間違いです。

試す

NSString *string = [[NSString alloc] initWithFormat:@"Hello %d", argc];

コンパイル時定数から文字列を初期化していないので、あなたが期待している方法のように振る舞う文字列を与えるはずです。ただし、ゾンビが有効になっていると警告され、期待する行動が得られますが、ゾンビがなければ、NSLOGはうまくいくかもしれません。文字列は扱われていますが、オブジェクト内のデータはまだメモリにあり、いくつかのメッセージに正しく応答する「ゴースト」を残します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top