2010-12-05 13 views
0

私が開発に新しいですし、これを把握することはできません。なぜこのコードは漏れていませんか?

for(NSString *collectionName in jsonObjects) 
    { 
    NSDictionary *collection = [[NSDictionary alloc] init]; 
    collection = [jsonObjects valueForKey:collectionName]; 
    NSArray *items = [[NSArray alloc] initWithArray:[collection valueForKey:@"items"]]; 
    NSNumber *lastAccess = [[NSNumber alloc] init]; 

    lastAccess = [collection valueForKey:@"lastAccess"]; 

    [items release]; 
    } 

それは、なぜ私がlastAccessのいずれかのコレクションを解放行うと、プログラムはEXC_BAD_ACCESSエラーでクラッシュすることを、理解していません...しかし、もし私がDONTをリリースした場合私はリークを取得します。誰もがこれに光を当ててください。私はあなたがallocを使用した場合、あなたは参照を所有していたので、解放しなければならないと思いましたか?

答えて

1
for(NSString *collectionName in jsonObjects) 
{ 
    NSDictionary *collection = [[NSDictionary alloc] init]; // Allocation 
    collection = [jsonObjects valueForKey:collectionName]; // overwriting above, LEAKS 
    NSArray *items = [[NSArray alloc] initWithArray:[collection valueForKey:@"items"]]; // Allocation 
    NSNumber *lastAccess = [[NSNumber alloc] init]; // Allocation 
    lastAccess = [collection valueForKey:@"lastAccess"]; // overwriting above, LEAKs 
    [items release]; 
} 

呼び出し「新しい」それがクラッシュの原因となります解放し、彼らはあなたが所有していないことを意味する「自動解放」されているオブジェクトへの参照を返します。それらを使用することはできますが、使用している機能の範囲内でのみ使用できます。後で使用するには、retainに電話する必要があります。したがって、アクセサ関数を呼び出すときは、必要な変数を宣言して新しいオブジェクトを作成する必要がありません。

alloccollectionあなたが空NSDictionaryを作成している場合には、新しいオブジェクトを作成しますが、あなたは、速やかに、あなたがリークを作成しますvalueForKey:このことから得る自動解放を参照して、新しいオブジェクトへの参照を上書きします。元々作成されたオブジェクトは解放されないためです。

おそらく私はマニュアルを読んで喜んで群衆によって答え、このような質問を持っていることの能力を備えたばかり雑用になってきたことを実感いますが、進行したい場合は、あなたが持っている必要があります。この

for(NSString *collectionName in jsonObjects) 
{ 
    NSDictionary *collection = [jsonObjects valueForKey:collectionName]; 
    NSArray *items = [collection valueForKey:@"items"]; 
    NSNumber *lastAccess = [collection valueForKey:@"lastAccess"]; 
} 

のようになります。見て、リンゴのドキュメントのほとんどは、これらのことが行くように例外的によく書かれています。 memory management guideは多くの疑問を解決します。

+0

ハーラルさん、メモリ管理ガイドを見てきましたが、間違っていると思います。私の最初のalloc/initを上書きすることについては何を言っているのですか?しかし、NSDictionary *コレクション= [jsonObjects valueForKey:collectionName];とNSDictionary *コレクション= [NSDictionary dictionaryWithDictionary:[jsonObjects valueForKey :collectionName]];つまり、これらの2つの宣言が機能的に同等であるかどうか、ドキュメントでは明確になりませんか? – Beliskna

+0

はい、いいえ、2つの呼び出しのどちらも所有しているものへの参照を返しません'alloc'または 'new'または 'copy'ですが、最初のものは新しい辞書を作成します。 dは与えられた辞書の値で初期化します(これはコンビニエンスコンストラクタと呼ばれます)。2番目のものは対応する辞書を返します。 [NSDictionary dictionaryWithDictionary:...]は[[NSDictionary alloc] initWithDictionary:...]より_different_です。2番目の_does_は、所有するオブジェクトを作成します –

+0

ありがとうHarald、あなたはとても役に立ちました。 – Beliskna

0

lastAccessポインタを再割り当てするだけで、allocNSNumberがリークします。 lastAccessが指し示すNSNumberオブジェクトの値を実際に設定する必要があります。

編集:私はいくつかのサンプルコードを配置していたが、私はコードサンプルは、上記の、あまりにも多くの問題を持っていることを今実現するので、私は、それを取っている

NSDictionaryのドキュメントをご覧ください。 collectionを使用すると、オブジェクトを作成してから、ポインタを別のものに再割り当てしてオブジェクトをリークします。これらの問題を解決したら、新しいコードで質問を更新することをお勧めします。

4

このコードにはいくつかの問題があります。現時点では、財団が一般的に使用されている特定の値をキャッシュすることは無視しています。

このパターンは意味をなさない:

NSDictionary *collection = [[NSDictionary alloc] init]; 
collection = [jsonObjects valueForKey:collectionName]; 

最初の行は、NSDictionaryのの(空の)インスタンスを作成し、2行目は速やかに基準を上書き。リークと全く無意味の両方。第1行に割当て/割当ての必要はない。後でlastAccessの場合も同じです。

releaseに2番目の行が所有権のない参照を返しているため、クラッシュする可能性があります。

クラッシュが発生した場合は、にバックトレースがあることに注意してください。この質問は、それが必要ではないほど簡単ですが、常にバックトレースに手がかりを求めます。

NSNumberまたはNSDictionaryインスタンスのいずれかのリークが実際には見られないことに注意してください。 NSNumberの場合、それは意味をなさない。しかし、空の辞書はかなり頻繁に使用され、シングルトンはメモリを節約します。

+0

シンプトンが何であるか分かりませんが、私はドキュメントをチェックします:) – Beliskna

0

上記@bbum後、私はこのようなコードを記述しますが:

for(NSString *collectionName in jsonObjects) 
{ 
NSDictionary *collection = [jsonObjects valueForKey:collectionName]; 
NSArray *items = [NSArray arrayWithObject:[collection valueForKey:@"items"]]; 
NSNumber * lastAccess = [collection valueForKey:@"lastAccess"]; 
} 

この場合、すべての変数は、自動解放されるので、それらを手動で解除する必要はありません。 「アロケーション」またはを含まない

関連する問題