1

Xcodeでゾンビを有効にして、プロセスがメモリリークでクラッシュするかどうかを確認しました。コードスニペットは次のとおりです。

- (NSString *)facVersion
{
    return facVersion;
}


- (void) setFacVersion:(NSString*)_facVersion
{
    if(facVersion != nil) [facVersion release];
    facVersion = [_facVersion retain];
}

今私が電話するとき

NSLog(@"%@", facVersion);
[self setFacVersion:facVersion];

コードがメッセージとともにクラッシュする

[CFString保持]:割り当て解除に送信されたメッセージ

問題が何であるか知っていますか?

4

4 に答える 4

5

これは、不適切に記述されたセッターの典型的な問題です。オブジェクト自体がプロパティのバッキングivarの最後の所有者である場合、プロパティをそれ自体に割り当てると、リリースによってオブジェクトの割り当てが効果的に解除され、同じ割り当て解除されたオブジェクトが保持されます。これは2つの方法で修正できます。割り当てられるオブジェクトがプロパティの現在の値と同じでないことを確認するか、最初に保持してから解放します。全体として、ソリューション1:

- (void) setFacVersion:(NSString*)_facVersion
{
    if (facVersion == _facVersion) return;
    [facVersion release];
    facVersion = [_facVersion retain];
}

解決策2:

- (void) setFacVersion:(NSString*)_facVersion
{
    [_facVersion retain];
    [facVersion release];
    facVersion = _facVersion;
}

ちなみに、オブジェクトをnil解放する前にオブジェクトが存在しないことを確認する必要はありません。Objective-CはJavaではありません。

于 2012-09-24T14:54:12.170 に答える
1

if (facVersion != _facVersion)セッターにあるはずです。そうしないと、同じオブジェクトを再度設定すると、セッターがそのオブジェクトを解放し(その結果、オブジェクトの割り当てが解除され)、その後は使用(保持)できなくなります。

- (void) setFacVersion:(NSString*)_facVersion
{
    if(facVersion != _facVersion) {
        [facVersion release];
        facVersion = [_facVersion retain];
    }
}

また、自動参照カウント(ARC)について知っていましたか?

自動参照カウント(ARC)は、Objective-Cオブジェクトの自動メモリ管理を提供するコンパイラ機能です。ARCを使用すると、保持および解放操作について考える必要がなく、興味深いコード、オブジェクトグラフ、およびアプリケーション内のオブジェクト間の関係に集中できます。

于 2012-09-24T14:53:27.337 に答える
0

すでに設定されているものと同じオブジェクトを渡すと、setFacVersion最初にそれが解放され、次に解放された(および割り当て解除された)オブジェクトを保持しようとします。

于 2012-09-24T14:52:47.710 に答える
0

保持を呼び出す前にリリースします。

リリースして保持する前にポインタを比較する場合を除いて、次のようなものを使用する必要があります。

- (void) setFacVersion:(NSString*)_facVersion
    [_facVersion retain];
    [facVersion release];
    facVersion = _facVersion;
}

そうすれば、あなたが示したように、ポインタが同じであれば、クラッシュすることはありません。

または、コンパイラにセッターを合成させます。

于 2012-09-24T14:53:04.067 に答える