在 NSConcreteMapTable 中使用 NSXMLParser 导致内存泄漏

发布于 2024-11-07 21:06:16 字数 4253 浏览 2 评论 0原文

我正在使用 NSXMLParser 并且出现指向 NSConcreteMapTable 的内存泄漏,无论是什么:

在此处输入图像描述

泄漏从我的 AppDelegate.m 调用解析器时,发生在这行代码:

在此处输入图像描述

我已经搜索了解决方案并且看不到我做错了什么。 这是我的代码。 非常感谢任何帮助。 lq

// * * * XMLParser.h * * *  

#import <Foundation/Foundation.h>

@protocol NSXMLParserDelegate;

@interface XMLParser : NSObject 
<NSXMLParserDelegate>
{
    NSMutableArray  *xmlArray;
    BOOL        storingCharacters;
    float       xmlDataVersion;
}

@property (nonatomic, retain) NSMutableArray *xmlArray;
@property (nonatomic)  BOOL storingCharacters;
@property (nonatomic, assign) float xmlDataVersion;

-(BOOL)parseXMLFileAtURL:(NSURL *)URL parseError:(NSError **)error;

@end

// * * * XMLParser.m * * *

#import "XMLParser.h"

@implementation XMLParser

@synthesize xmlArray;
@synthesize storingCharacters;
@synthesize xmlDataVersion;

- (BOOL)parseXMLFileAtURL:(NSURL *)URL parseError:(NSError **)error {

    BOOL result = YES;

    if (xmlArray == nil) {  
        // this array holds row data extracted from the XML parser didStartElement method                                           
        xmlArray = [[NSMutableArray alloc] init];
    }

    [[NSURLCache sharedURLCache] setMemoryCapacity:0];
    [[NSURLCache sharedURLCache] setDiskCapacity:0];
    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];

    if (parser != nil) {
        [parser setDelegate:self];
        [parser setShouldProcessNamespaces:NO];
        [parser setShouldReportNamespacePrefixes:NO];
        [[parser setShouldResolveExternalEntities:NO];
    }

    [parser parse];

    if (parseError && error) {
        *error = parseError;
        result = NO;
    }

    [parser release];
    return result;

}

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

    if (qName) {
        elementName = qName;
    }

    // Check the data version of the XML Data against my stored value

    if ([elementName isEqualToString:@"data"]) {

        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
        self.xmlDataVersion = [[attributeDict objectForKey:@"version"] floatValue];
        float storedDataVersion = [userDefaults floatForKey:kDataVersion];

       if (self.xmlDataVersion <= storedDataVersion) {
           // - - - - -> Abort parsing if the same or earlier data versions
           [parser abortParsing];
       }

    }

    if ([elementName isEqualToString:@"FirstColumnName"]) {
        storingCharacters = YES;
    } else if ([elementName isEqualToString:@"SecondColumnName"]) {
        storingCharacters = YES;
        // ... total of 16 elements
    }

}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    if (storingCharacters) {        
        [self.xmlArray addObject:string];
    }
}

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

    if (qName) {
        elementName = qName;
    }

    // - - - - -> If at the end of a data row, save changes to object model

    if ([elementName isEqualToString:@"ROW"]) {

        // - - - - -> Make sure the data has the required number of elements before taking any action

        if ([self.xmlArray count] == 16) {

            // … //Store or Update Data in SQLite store depending on data values    

        }

        [self.xmlArray removeAllObjects];   

    }

    storingCharacters = NO;
}

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


// * * * AppDelegate.m * * *

#import "XMLParser.h"

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(UIApplication *)application { 

    NSURL *xmlURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"FileName" ofType:@"xml"]];

    NSError *parseError = nil;

    XMLParser *xmlParse = [[XMLParser alloc] init];
    [xmlParse parseXMLFileAtURL:xmlURL parseError:&parseError];
    [xmlParse release];

    . . .

}

I'm using NSXMLParser and I get a memory leak that points to NSConcreteMapTable, whatever that is:

enter image description here

The leak occurs at this line of code when calling the parser from my AppDelegate.m:

enter image description here

I have searched for a solution and can't see what I'm doing wrong.
Here is my code.
Any help is greatly appreciated.
lq

// * * * XMLParser.h * * *  

#import <Foundation/Foundation.h>

@protocol NSXMLParserDelegate;

@interface XMLParser : NSObject 
<NSXMLParserDelegate>
{
    NSMutableArray  *xmlArray;
    BOOL        storingCharacters;
    float       xmlDataVersion;
}

@property (nonatomic, retain) NSMutableArray *xmlArray;
@property (nonatomic)  BOOL storingCharacters;
@property (nonatomic, assign) float xmlDataVersion;

-(BOOL)parseXMLFileAtURL:(NSURL *)URL parseError:(NSError **)error;

@end

// * * * XMLParser.m * * *

#import "XMLParser.h"

@implementation XMLParser

@synthesize xmlArray;
@synthesize storingCharacters;
@synthesize xmlDataVersion;

- (BOOL)parseXMLFileAtURL:(NSURL *)URL parseError:(NSError **)error {

    BOOL result = YES;

    if (xmlArray == nil) {  
        // this array holds row data extracted from the XML parser didStartElement method                                           
        xmlArray = [[NSMutableArray alloc] init];
    }

    [[NSURLCache sharedURLCache] setMemoryCapacity:0];
    [[NSURLCache sharedURLCache] setDiskCapacity:0];
    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];

    if (parser != nil) {
        [parser setDelegate:self];
        [parser setShouldProcessNamespaces:NO];
        [parser setShouldReportNamespacePrefixes:NO];
        [[parser setShouldResolveExternalEntities:NO];
    }

    [parser parse];

    if (parseError && error) {
        *error = parseError;
        result = NO;
    }

    [parser release];
    return result;

}

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

    if (qName) {
        elementName = qName;
    }

    // Check the data version of the XML Data against my stored value

    if ([elementName isEqualToString:@"data"]) {

        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
        self.xmlDataVersion = [[attributeDict objectForKey:@"version"] floatValue];
        float storedDataVersion = [userDefaults floatForKey:kDataVersion];

       if (self.xmlDataVersion <= storedDataVersion) {
           // - - - - -> Abort parsing if the same or earlier data versions
           [parser abortParsing];
       }

    }

    if ([elementName isEqualToString:@"FirstColumnName"]) {
        storingCharacters = YES;
    } else if ([elementName isEqualToString:@"SecondColumnName"]) {
        storingCharacters = YES;
        // ... total of 16 elements
    }

}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    if (storingCharacters) {        
        [self.xmlArray addObject:string];
    }
}

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

    if (qName) {
        elementName = qName;
    }

    // - - - - -> If at the end of a data row, save changes to object model

    if ([elementName isEqualToString:@"ROW"]) {

        // - - - - -> Make sure the data has the required number of elements before taking any action

        if ([self.xmlArray count] == 16) {

            // … //Store or Update Data in SQLite store depending on data values    

        }

        [self.xmlArray removeAllObjects];   

    }

    storingCharacters = NO;
}

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


// * * * AppDelegate.m * * *

#import "XMLParser.h"

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(UIApplication *)application { 

    NSURL *xmlURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"FileName" ofType:@"xml"]];

    NSError *parseError = nil;

    XMLParser *xmlParse = [[XMLParser alloc] init];
    [xmlParse parseXMLFileAtURL:xmlURL parseError:&parseError];
    [xmlParse release];

    . . .

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

离不开的别离 2024-11-14 21:06:16

我在另一篇 SO 帖子中找到了解决方案:

使用:

NSData * dataXml = [[NSData alloc] initWithContentsOfURL:URL];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:dataXml];
[dataXml release];

而不是:

NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];

泄漏消失。

I found a solution in another SO post:

Use:

NSData * dataXml = [[NSData alloc] initWithContentsOfURL:URL];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:dataXml];
[dataXml release];

Instead of:

NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];

The leak goes away.

§普罗旺斯的薰衣草 2024-11-14 21:06:16

这可能是 Apple 代码中的泄漏,因为 Foundation 被报告为“负责任的库”。您可能无能为力,只能向苹果报告该错误。

This is probably a leak in Apple code, since Foundation is reported as "Responsible Library". There's probably nothing you can do, but to report the bug to apple.

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