我使用的是XMLParser类,它包含一个带有XMLElement对象的数组。正在使用autorelease操作分配XMLElement。但是,出于某种原因,我在这一行上遇到了内存泄漏(使用工具):
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
答案 0 :(得分:3)
您必须在XMLParser中的currentElement
方法中发布dealloc
。
它创建为autorelease
,但随后被分配到retain
属性,因此您实际上保留了一次(这很好)。
更新:完成后应该self.currentElement = nil;
,而不是currentElement = nil;
。
答案 1 :(得分:2)
此:
self.currentElement = [[[XMLElement alloc] init] autorelease];
保留currentElement
(因为该属性是使用retain
声明的。)
稍后,在parser:didEndElement:namespaceURI:qualifiedName:
中,您执行此操作:
currentElement = nil;
导致泄漏,因为您没有发布currentElement
。
答案 2 :(得分:0)
从我在page上看到的,这是一个记录在案的苹果bug。我在一些应用程序中遇到了同样的问题......
答案 3 :(得分:0)
您的XMLParser
是否在后台线程上运行?如果是,则需要为该帖子创建NSAutoReleasePool
,以便[[[XMLElement alloc] init] autorelease]
来电。{/ p>
答案 4 :(得分:0)
而不是
@property(nonatomic, retain) XMLElement *parentElement;
必须是
@property(nonatomic, assign) XMLElement *parentElement;
您还需要从[parentElement release]
dealloc
原因是您正在创建循环依赖。父母与孩子和孩子的父母
当你重新分配解析器对象时,元素仍然在内存中用指针xount&gt; 0