iPhone:自动释放对象内存泄漏?

发布于 2024-09-28 02:49:08 字数 4569 浏览 2 评论 0原文

我正在使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

也只是曾经 2024-10-05 02:49:08

您必须在 XMLParser 的 dealloc 方法中释放 currentElement

它被创建为 autorelease ,但随后分配给 retain 属性,因此您实际上只保留它一次(这很好)。

更新:完成后,您应该执行 self.currentElement = nil;,而不是 currentElement = nil;

You must release currentElement in your dealloc method in XMLParser.

It's created as autorelease but then assigned to a retain property, so you are actually retaining it once (which is good).

UPDATE: you should do self.currentElement = nil; when you are done with it, not currentElement = nil;.

一口甜 2024-10-05 02:49:08

这:

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

保留 currentElement (因为该属性是用 retain 声明的)。

稍后,在 parser:didEndElement:namespaceURI:qualifiedName: 中,您执行以下操作:

currentElement = nil;

这会导致泄漏,因为您没有释放 currentElement

This:

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

retains currentElement (because the property is declared with retain).

Later, in parser:didEndElement:namespaceURI:qualifiedName:, you do this:

currentElement = nil;

which causes the leak because you are not releasing currentElement.

放飞的风筝 2024-10-05 02:49:08

从我在此页面上看到的,这是一个记录在案的苹果错误。我在一些应用程序中遇到了同样的问题......

From what I see on this page, this is a documented apple bug. I have experienced the same problem in some of my apps...

深府石板幽径 2024-10-05 02:49:08

您的 XMLParser 是否在后台线程上运行?如果是这样,您需要为该线程创建一个 NSAutoReleasePool ,以便您的 [[[XMLElement alloc] init] autorelease] 调用正常工作。

Is your XMLParser being run on a background thread? If so, you need to create an NSAutoReleasePool for that thread in order for your [[[XMLElement alloc] init] autorelease] call to work.

画中仙 2024-10-05 02:49:08

嗨,大家好。
原因只是一件简单的事情,

而不是

@property(nonatomic, retain) XMLElement *parentElement;

必须是

@property(nonatomic, assign) XMLElement *parentElement;

您还需要从 dealloc 中删除 [parentElement release]

原因是您正在创建循环引用。父级到子级,子级到父级

,当您释放解析器对象时,元素仍然出现在内存中,指针 xount > > 0

HI guys.
the reason is just one simple thing,

instead of

@property(nonatomic, retain) XMLElement *parentElement;

must be

@property(nonatomic, assign) XMLElement *parentElement;

also you need delete [parentElement release] from dealloc

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文