0

Objective C のメモリ管理を理解していなかったようです... ため息。

私は次のコードを持っています(私の場合、両方とも有効なデータで満たされていることに注意してくださいplacemark.thoroughfareplacemark.subThoroughfareしたがって、両方のif条件はTRUE

itemに結び付けられていManagedObjectContextます。itemなどの管理変数には、 でplace作成されたセッター/ゲッターがあり@dynamicます。したがって、宣言は

@property (nonatomic, retain) NSString *place;
@dynamic place;

コードの後半、ReverseGeocoderDelegate でアクセスします。

- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark {

if (placemark.thoroughfare) {
    [item.place release];
    item.place = [NSString stringWithFormat:@"%@ ", placemark.thoroughfare];        
} else {
    [item.place release];
    item.place = @"Unknown Place";
}
if (placemark.thoroughfare && placemark.subThoroughfare) {
// *** problem is here ***
    [item.place release];
    item.place = [NSString stringWithFormat:@"%@ %@", placemark.thoroughfare , placemark.subThoroughfare];
}

コード内のマークされた場所で解放しないとitem.place、Instruments はそこでメモリ リークを検出します。item.placeその場合、問題のあるメソッドの外部にアクセスしようとするとすぐにプログラムがクラッシュします。

何か案は?

4

2 に答える 2

2

まず、ロジックを次のように変更します。

NSString *newPlace = nil;

if (placemark.thoroughfare && placemark.subThoroughfare) {
    newPlace = [NSString stringWithFormat:@"%@ %@", placemark.thoroughfare , placemark.subThoroughfare];
}
else {
    if (placemark.thoroughfare) {
        newPlace = [NSString stringWithFormat:@"%@ ", placemark.thoroughfare];
    }
    else {
        newPlace = @"Unknown Place";
    }
}

item.place = newPlace;    // Either nil of valid string can be assigned to

単純にポインターを再初期化するために release を使用することは、あまり推奨されていません。メモリを節約する場合は、これを行う必要はありません。

以前のロジックでは、releaseを 2 回行います。release が最初に行うことは、単純にデクリメントすることretainCountです。0 の場合、オブジェクトは割り当て解除されます。オブジェクトは、retainCount0 になるまで割り当て解除されません。

あなたのアイテムがプロパティ持っていると仮定すると、文字列をstringWithFormat:返すので、2番目のリリースでは、とにかくautoreleasedどうなるかをリリースしようとしていました.autoreleased

オブジェクトを複数回クリアする最善の方法は、単純に代入nilすることです。

于 2011-01-16T13:21:20.687 に答える
1

どこでも `[item.place release]' を行う必要がないので、出発点はプロパティについて読み直すことです。したがって、それらを削除できます。そのプロパティを有効にするためにランタイムによって作成された動的コードは、以前に割り当てられたすべての解放を自動的に処理します。

また、[NSString stringWithFormat:...自動解放オブジェクトを作成します (それを知っているかどうかはわかりません:-)。これは、変数 (プロパティではない) のメモリを手動で管理する場合は、それを保持/解放する必要があることを意味します。しかし、プロパティを使用しているため、そうではありません。

なぜ計測器がメモリ リークを検出するのかわかりません。おそらく、より上位のコードがそれに関係しています。たとえば、あなたが行った場合item.place = [NSString alloc] initWith...];、それが必要になると思います。

リリースによって保持カウントがゼロになり、exec bad access エラーが発生したことが原因であると思われるクラッシュです。

それが役立つことを願っています。

于 2011-01-16T11:48:29.550 に答える