3

更新:コードを編集しましたが、問題は解決しません...

皆さん、こんにちは。
これは私の最初の投稿です。この場所は、多くの質問を解決するための優れたリソースであることがわかりました。普段は自分で何とかしようと頑張っているのですが、今回は何が悪いのかさっぱり分からないので、誰か助けていただければと思います。
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 を解析すると、インストルメントにリークが表示されません。次に解析すると、多くのリーク (NSCFString / NSCFDictionary) が発生します。
Instrumentsは、リークされたオブジェクトを掘り下げると、 CXMLNode.m 内のこの部分を示します。

theStringValue = [NSString stringWithUTF8String:(const char *)theXMLString];
if ( _node->type != CXMLTextKind )
   xmlFree(theXMLString);
}

return(theStringValue);  

私は本当に長い時間を費やし、これを修正するために複数のアプローチを試みましたが、これまでのところ役に立ちませんでした。

どんな助けでも大歓迎です、ありがとう!

4

3 に答える 3

3

問題は次の行にある可能性があります。

[self.mobil addObject:[product copy]];

のコピーを呼び出すproductと、保持カウントが 1 の新しい NSMutableDictionary インスタンスが作成されます。ただし、メッセージmobilを送信すると、インスタンスはコピーの保持カウントをインクリメントするため、コピーの保持カウントは 2 になります。一般的に言えば、オブジェクトはそれ自身のオブジェクト メモリを処理する責任があるため、またはにaddObject:メッセージを送信するときはいつでも、オブジェクトを直接渡すことができます。保持する必要がある場合、渡したオブジェクトを保持するのは受信側の責任です。setFoo:addObject:

コピーを変数に割り当てていないため、コピーに関心がなくなったので、コピーの保持カウントを減らすために使用できるポインターがありません。そのため、mobilある時点で製品コピーをリリースしても、 copy の保持カウントが 0 に達することはありません。for[product release]ループの最後のステートメントは、product作成したコピーではなく、元のオブジェクトを解放します。

代わりに、次のことを試して、楽器がより快適になるかどうかを確認してください。

[self.mobil addObject:product];
于 2009-06-20T11:18:55.593 に答える
1

私は自分で問題を解決しました。ちょっとばかげていますが、誰かが同じことに遭遇するかもしれないので、ここに投稿します。

1)次のようなインスタンス変数として可変配列を設定しました:

@interface XMLParser : NSObject {

// ...  
NSMutableArray *mobil;  
// ...  
}   
@property(nonatomic, retain) NSMutableArray *mobil;  
@end  

内部の新しいデータを復元したいときはいつでも、次のようにしました:
self.mobil = nil;
これは私がやりたいことではなかったので、これがより良いアプローチです:
[self.mobil removeAllObjects];

2) リークを修正するには、dealloc メソッドを次のようにする必要があります (mobil はプロパティとして定義されているため):
-(void)dealloc {
[mobil release];
self.mobil = nil;
}

ふぅ、それを見つけるのは大変な作業でした-他の誰かの時間を節約できることを願っています:-)

于 2009-06-20T15:41:05.300 に答える
1

簡単に言えば、 を使用するたびに、どこかで/copyも使用する必要があります。releaseautorelease

この場合、元のバージョンをコピーした後copyは何もしていないため、最初から使用しない方が簡単です。product

于 2009-06-20T11:54:14.617 に答える