3

これは私のiPhoneコードの(非常に)単純化されたバージョンです:

@interface x {
NSString * name1;
NSString * name2;
}

-init {
name1 = @"";
name2 = @"";
}

-(void) a {
Foo * foo = [Foo 割り当て];
name1 = @"うーん";
name2 = [フーバー]; // return a (NSString *)
[foo release];
}

-(void) b {
NSLog(@"%@", name1); // 動作します
NSLog(@"%@", name2); // そこで EXC_BAD_ACCESS を取得します...
}

なぜ私はこの問題を抱えているのですか? どうすれば解決できますか?
ありがとう !

編集:問題を解決しただけですが、「保持」を忘れていました...

4

3 に答える 3

1

Cocoa メモリ管理ガイドを読む必要があります。

コードで実行していることのいくつかは、ココア メモリ管理の基本的な概念を把握していないことを示しています。

例えば:

[Foo alloc];

「foo」を初期化していません。alloc結合しinitて一緒に呼び出すことは一般的な方法です。たとえば、[[Foo alloc] init];これにより、オブジェクトのメンバーと状態が作成後に期待どおりになることが保証されます。

name2 = [foo bar]; // returns a (NSString *)

このbarメソッドはautoreleased文字列を返す可能性があります。に割り当てた後は保持していないname2ため、メソッドが戻った後、しばらくして割り当てが解除されます。これが、コードがクラッシュする理由です。割り当てが解除されたオブジェクトにアクセスしようとしています。指していたオブジェクトname2は解放され、割り当てが解除されましたが、ポインターは nil に設定されていませんでした。つまり、ポインターが指しているメモリには何でも含めることができます。未定義です。

機能する理由name1は、Cocoa でリテラル @"" 文字列を使用する際の特別な考慮事項のためです。文字列がこのように使用されると、「内部化」されます。同じテキストを含む 2 つのリテラル文字列を作成すると、両方の文字列がメモリ内の 1 つのオブジェクトを指すようにシステムが最適化します。

つまり、次のようなコードがあるとします。

NSString *myString1 = @"hello";
NSString *myString2 = @"hello";

NSLog(@"string1: %p, string2: %p", myString1, myString2);

次のようなメッセージになりますstring1: 0x123456, string2: 0x123456。ここで注目すべき重要な点は、メモリ アドレスが同じであることです。コード内では異なるインスタンスですが、文字列は同じオブジェクトを指しています。

于 2010-04-18T00:15:31.987 に答える
0

昨日、EXC_BAD_ACCESS エラーが発生しました。削除されたオブジェクトを呼び出していたことが判明しrelease、それを使用しようとしました。

あなたはあなたがrelease想定されていないものを呼んでいませんか?

フレンドリーなリマインダー:オブジェクトに対してallocまたはを呼び出さない場合は、 を呼び出さないでください。あなたが提供したコードでは、これが問題であるようには見えません。しかし、念のためにこれを指摘したかったのです。retainrelease

于 2010-04-17T20:09:04.143 に答える
0

ジョエルは正しいです。[foo bar] 関数を調べてみてください。その関数でオブジェクトを解放している可能性があります

于 2010-04-17T20:12:43.077 に答える