3

XMLElement オブジェクトの配列を含む XMLParser クラスを使用しています。XMLElement は autorelease 操作を使用して割り当てられています。ただし、何らかの理由で、この行で (instruments を使用して) メモリ リークが発生しています。

self.currentElement = [[[XMLElement alloc] init] autorelease];

また、呼び出し元クラスで XMLParser オブジェクトを解放しています。以下の XMLParser ソース コードの「問題のある」行をコメントとして強調表示しました。

私は本当にそれを修正するためにあらゆることを試みましたが、残念ながら、なぜこれが起こっているのかまったくわかりません. どんな助けでも大歓迎です!

どうもありがとうございました!

// --- XMLElement

#import <Foundation/Foundation.h>


@interface XMLElement : NSObject {
     NSDictionary *attributes;
     NSMutableArray *children;
     NSString *textValue;
     NSString *tagName;
     XMLElement *parentElement;
}

-(id) init;
-(void) addChild:(XMLElement*) child;

@property(nonatomic, retain) NSDictionary *attributes;
@property(nonatomic, retain) NSMutableArray *children;
@property(nonatomic, retain) NSString *textValue;
@property(nonatomic, retain) NSString *tagName;
@property(nonatomic, retain) XMLElement *parentElement;

@end


#import "XMLElement.h"


@implementation XMLElement

@synthesize attributes, children, textValue, parentElement, tagName;

-(id)init {
     if(self = [super init]) {
          children = [[NSMutableArray alloc] init];
     }
     return self;
}

-(void) addChild:(XMLElement*) child{
     [self.children addObject:child];
}

- (void)dealloc {
     [attributes release];
     [children release];
     [textValue release];
     [tagName release];
     [parentElement release];
    [super dealloc];
}

@end





// --- XMLParser

#import <Foundation/Foundation.h>
#import "XMLElement.h"

@interface XMLParser : NSObject<NSXMLParserDelegate> {
     XMLElement *currentElement;
     XMLElement *currentParentElement;
     NSMutableString *currentElementValue;
}

- (BOOL)parseData: (NSData*) dataToParse;

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
     attributes:(NSDictionary *)attributeDict;

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string;

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;

@property (nonatomic, retain) XMLElement *currentParentElement;
@property (nonatomic, retain) XMLElement *currentElement;
@property (nonatomic, retain) NSMutableString *currentElementValue;

@end


#import "XMLParser.h"


@implementation XMLParser

@synthesize currentElementValue, currentElement, currentParentElement;

- (BOOL)parseData: (NSData*) dataToParse {

     NSXMLParser *parser = [[NSXMLParser alloc] initWithData:dataToParse];
     [parser setDelegate:self];
     BOOL success = [parser parse];
     [parser release];
     return success;
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
     attributes:(NSDictionary *)attributeDict{
     if(currentElement){
          self.currentParentElement = currentElement;
     }


     // ------------------------------------------------------------
     // Instruments is marking this line as source of the leak with 90%
     self.currentElement = [[[XMLElement alloc] init] autorelease];
     // --------

     currentElement.tagName = elementName;
     currentElement.attributes = attributeDict;
     currentElement.parentElement = self.currentParentElement;
     if(self.currentParentElement){
          [self.currentParentElement addChild:currentElement]; // and this one with 10%
     }

     self.currentElementValue = nil;
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
     if(!currentElement) {
          return;
     }

     if(currentElementValue == nil)
          self.currentElementValue = [NSMutableString stringWithString:string];
     else
          [currentElementValue appendString:string];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
     if(currentElement == nil){
          if( currentParentElement.parentElement){
               self.currentParentElement = currentParentElement.parentElement;
          }
     }else{
          currentElement.textValue = currentElementValue; 
          [currentElementValue release];
          currentElementValue = nil;
          self.currentParentElement = currentElement.parentElement;
          currentElement = nil;
     }
}

- (void)dealloc {
     [currentParentElement release];
     [currentElement release];
    [super dealloc];
}

@end
4

5 に答える 5

3

XMLParser のメソッドで解放currentElementする必要があります。dealloc

として作成されますがautorelease、プロパティに割り当てられるため、retain実際には一度保持されます (これは良いことです)。

更新:self.currentElement = nil;ではなく、完了したら行う必要がありますcurrentElement = nil;

于 2010-10-19T12:40:32.300 に答える
2

これ:

self.currentElement = [[[XMLElement alloc] init] autorelease];

保持しますcurrentElement(プロパティが で宣言されているためretain)。

後で、 でparser:didEndElement:namespaceURI:qualifiedName:次のようにします。

currentElement = nil;

リリースしていないため、リークが発生しますcurrentElement

于 2010-10-19T12:40:48.773 に答える
0

XMLParserバックグラウンドスレッドで実行されていますか?その場合、呼び出しを機能NSAutoReleasePoolさせるには、そのスレッドの を作成する必要があります。[[[XMLElement alloc] init] autorelease]

于 2010-10-19T14:50:46.880 に答える
0

このページに表示されている内容から、これは文書化された Apple のバグです。一部のアプリで同じ問題が発生しました...

于 2010-10-19T14:12:10.507 に答える
0

こんにちは、みんな。理由は単純なことで、

それ以外の

@property(nonatomic, retain) XMLElement *parentElement;

でなければなりません

@property(nonatomic, assign) XMLElement *parentElement;

[parentElement release]また、から削除する必要がありますdealloc

その理由は、循環参照を作成しているためです。親から子へ、子供から親へ

パーサーオブジェクトを実現しているとき、要素は引き続きメモリ内でポインタ xount > 0 で発生します

于 2010-10-28T11:11:50.497 に答える