代码中的内存泄漏

时间:2011-09-16 19:45:29

标签: iphone objective-c ios xcode

  

可能重复:
  Memory Leak In line of code

这段代码工作正常,但它给我一个代码行中的内存泄漏,该行显示了紫色在仪器中显示的泄漏,提到100.0%的行是

NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];

我会告诉你我的代码这是appdelegate文件didFinishLaunchingWithOptions方法: -

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSURL *url = [[NSURL alloc] initWithString:@"http://www.xyz.com/news.php?page_id=1"];

    NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
    [url release];

    //Initialize the delegate.
    NewsParser *parser = [[NewsParser alloc] initXMLParser];

    //Set delegate
    [xmlParser setDelegate:parser];

    //Start parsing the XML file.
    BOOL success = [xmlParser parse];

    if(success)
        NSLog(@"No Errors");
    else
        NSLog(@"Error Error Error!!!");

    [parser release];
    [xmlParser release];


    // Override point for customization after application launch.
    // Add the navigation controller's view to the window and display.
    self.window.rootViewController = self.navigationController;
    [self.window makeKeyAndVisible];
    return YES;
}

此代码来自NewsParser文件NSXMLParser方法: -

- (NewsParser *) initXMLParser {
    [super init];
    appDelegate = (TWAppDelegate *)[[UIApplication sharedApplication] delegate];
    return self;
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName 
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName 
    attributes:(NSDictionary *)attributeDict {
    if([elementName isEqualToString:@"posts"]) {
        appDelegate.newsArray = [[NSMutableArray alloc] init];
    }
    else
    {
        if([elementName isEqualToString:@"page"])
        {

            aNewsInfo = [[NewsInfo alloc] init];
            aNewsInfo.page = [[attributeDict objectForKey:@"id"] integerValue];


        }
        if(![elementName compare:@"smallimage"])
        {
            currentElementValue = [NSMutableString string];

        }
        if(![elementName compare:@"largeimage"])
        {
            currentElementValue = [NSMutableString string];
        }
    }
    NSLog(@"Processing Element :%@",elementName);
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { 
    if(!currentElementValue) 
        currentElementValue = [[[NSMutableString alloc] initWithString:string] autorelease];
    else
        [currentElementValue appendString:string];

    NSLog(@"Processing Value: %@", currentElementValue);
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    if([elementName isEqualToString:@"posts"])
        return;
    if([elementName isEqualToString:@"page"]) {
        [appDelegate.newsArray addObject:aNewsInfo];
        NSLog(@"%d",[appDelegate.newsArray count]);
        NSLog(@"%@",aNewsInfo.title);
        NSLog(@"%@",aNewsInfo.fulltext);
        [aNewsInfo release];
        aNewsInfo = nil;
    }
    else {
        if ([elementName isEqualToString:@"smallimage"])
        {
            NSURL *url = [NSURL URLWithString:currentElementValue];
            NSData *data = [NSData dataWithContentsOfURL:url];
            UIImage *image = [[UIImage alloc] initWithData:data]; 
            [aNewsInfo setSmallImageData:image];
        }
        if(![elementName compare:@"largeimage"])
        {
            NSURL *imageURL = [NSURL URLWithString:currentElementValue];
            NSData *data =  [NSData dataWithContentsOfURL:imageURL];
            UIImage *image = [[UIImage alloc] initWithData:data];
            [data release];
            [aNewsInfo setLargeImageData:image];
        }
        [aNewsInfo setValue:currentElementValue forKey:elementName];
        [currentElementValue release];
        currentElementValue = nil;
    }
}

任何一个PLZ告诉我如何克服这个漏洞我即将在应用程序商店提交我的应用程序,但这是唯一的漏洞,请提出你的建议。

...谢谢

3 个答案:

答案 0 :(得分:5)

您可以运行静态分析仪,它通常会显示泄漏的原因。它的 菜单中的“分析”,“构建”命令旁边。

答案 1 :(得分:2)

您知道如果只使用@property@synthesize,然后正确使用getter和setter,您可以在99%的时间内减少此问题。

这条线看起来像对我来说最可疑之一

appDelegate.newsArray = [[NSMutableArray alloc] init];

假设newsArray被声明为retain的属性,在这种情况下,您将分配一个NSMutableArray,其保留+1,然后将其设置为一个setter(如果设置为retain)将再给出+1。

这条线对我来说看起来不太好

currentElementValue = [NSMutableString string];

您正在为ivar指定一个自动释放NSMutableString而没有ivar保留它。这可能会导致以后更难以跟踪问题。

有人指出init方法没有正确编写 - 这不是问题,但仍应修复。它看起来应该更像这样

- (NewsParser *)initXMLParser 
{
    self = [super init];
    if (self) {
        appDelegate = (TWAppDelegate *)[[UIApplication sharedApplication] delegate];
    }
    return self;
}

答案 2 :(得分:1)

而不是做

NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];

执行以下操作

NSData *xmlData = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]]; 
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:xmlData];

initWithContentsOfURL没有正确释放url,因此内存泄漏。 幸运的是,initWithData没有这个问题,提供了解决此内存泄漏的巧妙方法。