iPhone:自动释放对象内存泄漏?
我正在使用 XMLParser 类,它包含一个带有 XMLElement 对象的数组。 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
I am using the XMLParser class, which contains an array with XMLElement objects. The XMLElement is being allocated using the autorelease operation. However, for some reason I'm getting a memory leak (using instruments) on this line:
self.currentElement = [[[XMLElement alloc] init] autorelease];
I'm also releasing the XMLParser object in the caller class. I've highlighted the "problematic" lines in the XMLParser source code below as comment.
I really tried everything to fix it, but unfortunately I do not understand why this is happening at all. Any help is appreciated!
Thank you very much!
// --- 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您必须在 XMLParser 的
dealloc
方法中释放currentElement
。它被创建为
autorelease
,但随后分配给retain
属性,因此您实际上只保留它一次(这很好)。更新:完成后,您应该执行
self.currentElement = nil;
,而不是currentElement = nil;
。You must release
currentElement
in yourdealloc
method in XMLParser.It's created as
autorelease
but then assigned to aretain
property, so you are actually retaining it once (which is good).UPDATE: you should do
self.currentElement = nil;
when you are done with it, notcurrentElement = nil;
.这:
保留
currentElement
(因为该属性是用retain
声明的)。稍后,在
parser:didEndElement:namespaceURI:qualifiedName:
中,您执行以下操作:这会导致泄漏,因为您没有释放
currentElement
。This:
retains
currentElement
(because the property is declared withretain
).Later, in
parser:didEndElement:namespaceURI:qualifiedName:
, you do this:which causes the leak because you are not releasing
currentElement
.从我在此页面上看到的,这是一个记录在案的苹果错误。我在一些应用程序中遇到了同样的问题......
From what I see on this page, this is a documented apple bug. I have experienced the same problem in some of my apps...
您的
XMLParser
是否在后台线程上运行?如果是这样,您需要为该线程创建一个NSAutoReleasePool
,以便您的[[[XMLElement alloc] init] autorelease]
调用正常工作。Is your
XMLParser
being run on a background thread? If so, you need to create anNSAutoReleasePool
for that thread in order for your[[[XMLElement alloc] init] autorelease]
call to work.嗨,大家好。
原因只是一件简单的事情,
而不是
必须是
您还需要从
dealloc
中删除[parentElement release]
原因是您正在创建循环引用。父级到子级,子级到父级
,当您释放解析器对象时,元素仍然出现在内存中,指针 xount > > 0
HI guys.
the reason is just one simple thing,
instead of
must be
also you need delete
[parentElement release]
fromdealloc
reason is that you are creating cyclic referances. parent to child and chils to parent
and when you are realesing parser object the elements still ocurrs in memory with pointer xount > 0