3

私はObjective-Cの理解を固めるためにいくつかの探索的コードを書いていましたが、私はこの例に出くわしましたが、私は完全には理解していません。このメソッドを定義し、コードを実行します。

- (NSString *)stringMethod
{
    NSString *stringPointer = [[NSString alloc] initWithFormat:@"string inside stringPointer"];
    [stringPointer release];
    [stringPointer release];
    NSLog(@"retain count of stringPointer is %i", [stringPointer retainCount]);
    return stringPointer;
}

コードを実行してこのメ​​ソッドを呼び出した後、いくつかのことに気付きました。

  1. 通常、保持カウントがゼロになった後に割り当てが解除されたと思われるものにアクセスしようとすると、EXC_BAD_ACCESSエラーが発生します。ここでは、代わりにmallocの「ダブルフリー」エラーが発生します。何故ですか?

  2. コードに「[stringPointerrelease]」の行数を追加しても、NSLogは保持カウント1を報告します。リリースを追加すると、「ダブルフリー」エラーが増えるだけです。リリースステートメントが期待どおりに機能しないのはなぜですか?

  3. stringPointerをオーバーリリースし、「ダブルフリー」エラーをたくさん受け取りましたが、戻り値は何も起こらなかったかのように機能します(戻り値を報告する別のNSLogがメインコードにあります)。プログラムは引き続き正常に実行されます。繰り返しますが、なぜこれが起こるのか誰かが説明できますか?

これらの例はかなり些細なことですが、私は何が起こっているのかを完全に把握しようとしています。ありがとう!

4

3 に答える 3

6

2回リリースし、2つのdeallocメッセージが発生するため、ダブルフリーエラーが発生します。= P

リリースしたからといって、そのメモリアドレスのデータがすぐに破棄されるわけではないことに注意してください。未使用としてマークされているだけなので、カーネルは、将来のある時点で、別のデータに自由に使用できることを認識します。その時点まで(アプリスペースでは完全に非決定的です)、データはそこに残ります。

繰り返しになりますが、解放(および割り当て解除)は、バイトレベルでの即時のデータ破壊を必要としません。これはカーネルの単なるマーカーです。

于 2009-10-07T01:44:29.980 に答える
3

ここで起こっていることがいくつかあります。まず、オブジェクトの割り当てを解除しても、オブジェクトが以前に占有していたメモリが必ずしもクリアされるとは限りません。それはただそれを無料としてマークします。そのメモリを再利用するような何かをしない限り、古いデータはただぶらぶらします。

NSStringの特定のケースでは、これはクラスクラスターです。つまり、alloc / initから取得する実際のクラスは、NSStringインスタンスではなく、NSStringの具体的なサブクラスです。「定数」文字列の場合、これは非常に軽量な構造であり、C文字列定数へのポインタを維持するだけです。そのストライキングのコピーをいくつ作成したり、リリースした回数に関係なく、定数C文字列へのポインタの有効性に影響を与えることはありません。

この場合、および可変文字列、または実際にフォーマット文字と引数を使用するフォーマットされた文字列の場合と同様に、[stringPointerクラス]を調べてみてください。おそらく、3つすべてが異なるクラスを持っていることが判明するでしょう。

于 2009-10-07T01:58:54.843 に答える
0

常に1を出力するretainCountは、おそらく最適化が原因です-リリースが割り当て解除されることに気付いた場合、retainCountを更新する理由はありません(この時点では、オブジェクトへの参照はありません)。retainCountを更新する代わりに割り当てを解除するだけです。

于 2009-10-07T01:52:05.303 に答える