2

私は客観的な c メモリ管理 (ARC なし) を学んでおり、いくつかの一般的な問題に遭遇しました。ここで何度か出てきたので、「一体何!?」ではなく、「正しく理解できていますか?」と聞いています。

問題:

ドキュメントには次のように記載されています。

- (NSString *)fullName {

    NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@",

                                          self.firstName, self.lastName] autorelease];

    return string;

}

alloc によって返された文字列を所有しています。メモリ管理規則に従うには、文字列への参照を失う前に、文字列の所有権を放棄する必要があります。ただし、release を使用すると、文字列が返される前に割り当てが解除されます (メソッドは無効なオブジェクトを返します)。autorelease を使用すると、所有権を放棄することを示しますが、メソッドの呼び出し元は、割り当てが解除される前に、返された文字列を使用できます。

それでは、試してみましょう:

// Method defined in one on my class:
-(NSString*) returnString {
    NSString* str = [[NSString alloc] initWithString:@"returned String"]; 
    NSLog(@"1) Address in method = %p", [str self]);
    [str release];
    NSLog(@"2) Address in method = %p", [str self]);
    return str; 
 }

// In main: 
        NSString* str = [myObject returnString];
        NSLog(@"String is: [%@]", str);
        NSLog(@"3) Address in main = %p", [str self]);

-

 Output:
    1) Address in method = 0x100002a50
    2) Address in method = 0x100002a50
    String is: [returned String] // <--
    3) Address in main = 0x100002a50

それで、私がよく理解していれば、問題は、正確にいつメモリが解放されるかを予測するのが難しいということですか? または、実際には、メモリ内の特定の場所が「解放済み」としてマークされているだけで、それだけです... そうですか?

4

2 に答える 2

7

NSString多くの状況で割り当て/割り当て解除を回避することについて非常に賢明です。これは、Objective C での割り当て解除のテストとメモリ管理のセマンティクスの学習には非常に悪い選択です。

この場合、リテラルからオブジェクトを割り当てています (割り当てが解除されることはありません)。新しく初期化されたオブジェクトは不変オブジェクトのコピーであるため、イニシャライザはリテラルを返すだけです (この場合も、割り当てが解除されることはありません)。

たとえば、NSObjectまたはカスタム派生クラスを使用して、割り当て解除をテストする必要があります。

別の大きな助けになるのは、ゾンビを有効にすることです。これにより、割り当て解除されたオブジェクトへの最初のアクセスにすぐに気付くことができます。

それで、私がよく理解していれば、問題は、正確にいつメモリが解放されるかを予測するのが難しいということですか?

オブジェクトの有効期間は完全に決定論的です (非推奨の Mac OS X ガベージ コレクターを使用しない場合)。唯一の問題は、自動解放プールに関するものです。通常、オブジェクトが自動解放されているかどうかはわからないため、予想よりも長く存続するかどうかを推測することはできません。

于 2013-03-11T10:20:46.423 に答える
0
NSString *str1 =@"parag";
NSString*str2=[[NSString alloc] initWithString:@"parag"];
NSLog(@"%p %p", str1, str2); //str1 and str2 both are same  
  //  0x100002098 0x100002098

これは内部最適化に関連しています。str2 を解放する必要があります。

注:これは、コンパイラと initWithString: メソッドの文書化されておらず保証されていない動作に依存しています。どちらもいつでも変更される可能性があります。

于 2013-03-11T10:52:00.570 に答える