XMLパーサーでの奇妙なiPhoneメモリリーク
-
06-07-2019 - |
質問
更新:コードを編集しましたが、問題は解決しません...
こんにちは、
これは私の最初の投稿です-私はこの場所が私の質問の多くを解決するための素晴らしいリソースであることを発見しました。通常、私は自分で何かを修正するために最善を尽くしますが、今回は何が間違っているのか本当にわかりませんので、誰かが私を助けてくれることを願っています。
TouchXMLを使用していくつかのxmlファイルを解析するiPhoneアプリを構築しています。 XMLParserクラスがあり、ダウンロードと結果の解析を行います。 XMLParserの同じインスタンスでxmlファイルを複数回解析すると、メモリリークが発生します。
解析スニペットの1つ(関連部分のみ)を次に示します。
for(int counter = 0; counter < [item childCount]; counter++) {
CXMLNode *child = [item childAtIndex:counter];
if([[child name] isEqualToString:@"PRODUCT"])
{
NSMutableDictionary *product = [[NSMutableDictionary alloc] init];
for(int j = 0; j < [child childCount]; j++) {
CXMLNode *grandchild = [child childAtIndex:j];
if([[grandchild stringValue] length] > 1) {
NSString *trimmedString = [[grandchild stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[product setObject:trimmedString forKey:[grandchild name]];
}
}
// Add product to current category array
switch (categoryId) {
case 0:
[self.mobil addObject: product];
break;
case 1:
[self.allgemein addObject: product];
break;
case 2:
[self.besitzeIch addObject: product];
break;
case 3:
[self.willIch addObject: product];
break;
default:
break;
}
[product release];
}
}
初めて、xmlを解析し、計測器にリークが表示されないようにします。次回、XMLを解析すると、多くのリーク(NSCFString / NSCFDictionary)が発生しました。
Instrumentsは、リークされたオブジェクトを掘り下げると、 CXMLNode.m内のこの部分を示します。
theStringValue = [NSString stringWithUTF8String:(const char *)theXMLString];
if ( _node->type != CXMLTextKind )
xmlFree(theXMLString);
}
return(theStringValue);
私は本当に長い時間を費やし、これを修正するために複数のアプローチを試みましたが、今のところ役に立たないために、おそらく何か重要なものを見逃していますか?
ご協力ありがとうございます!ありがとうございます!
解決
問題は次の行にある可能性が高い:
[self.mobil addObject:[product copy]];
product
のコピーを呼び出すことにより、保持カウント1で新しいNSMutableDictionaryインスタンスを作成しています。ただし、 mobil
インスタンスは、コピーの保持をインクリメントします addObject:
メッセージを送信するときにカウントされるため、コピーの保持カウントは2になります。一般的に、オブジェクトは独自のオブジェクトメモリを処理するため、 setFoo:
または addObject:
を使用すると、オブジェクトが自動解放された場合でも、呼び出し直後にオブジェクトを解放する場合でも、オブジェクトを直接渡すことができます。受け渡す必要がある場合、受け渡しているオブジェクトを保持するのは受信者の責任です。
どの変数にもコピーを割り当てなかったため、興味がなくなったため、コピーの保持カウントを減らすために使用できるポインターがありません。 code>はある時点で製品のコピーをリリースします。コピーが保持カウント0に達することはありません。forループの最後にある [product release]
ステートメントは、元の product 作成したコピーではなくcode>オブジェクト。
代わりに、以下を試して、楽器が幸せかどうかを確認します。
[self.mobil addObject:product];
他のヒント
簡単に言えば、 copy
を使用するたびに、 release
/ autorelease
のいずれかを使用する必要があります。
そして、この場合、最初の場所で copy
を使用しないのがさらに簡単な答えです。なぜなら、 product
の元のバージョンでは何もしていないからです。コピーしました。
自分で問題を修正しました。それはちょっと馬鹿げたものでしたが、誰かが同じものに出くわすかもしれないので、ここに投稿します。
1)可変配列を次のようなインスタンス変数として設定しました:
@interface XMLParser : NSObject {
// ...
NSMutableArray *mobil;
// ...
}
@property(nonatomic, retain) NSMutableArray *mobil;
@end
自分の内部で新しいデータを復元したいたびに:
self.mobil = nil;
これは私がやりたかったことではなかったので、これはより良いアプローチです:
[self.mobil removeAllObjects];
2)リークを修正するには、deallocメソッドを次のようにする必要があります(mobilはプロパティとして定義されているため):
-(void)dealloc {
[モービルリリース];
self.mobil = nil;
}
うーん、それを見つけるのは大変な作業でした-他の誰かが時間を節約できることを願っています:-)