任何人都可以识别泄漏,有帮助吗?

时间:2009-11-04 10:52:20

标签: iphone memory-leaks instruments

我开发了我的iPhone应用程序,现在我正在用仪器测试它以找到内存泄漏。

我有我的appDelegate类,我在其中从Web服务获取数据,然后解析它然后将其存储在数组中..

这是我的applicationDidFinishLaunching方法:

UIApplication* app = [UIApplication sharedApplication]; 
app.networkActivityIndicatorVisible = YES; 
serviceURL = [[NSUserDefaults standardUserDefaults] stringForKey:@"readOnly_key"];
NSLog(@"text = %@",serviceURL);

if(serviceURL == nil)
{
    //We set the default values from the settings bundle.

    //Get the bundle path
    NSString *bPath = [[NSBundle mainBundle] bundlePath];
    NSString *settingsPath = [bPath stringByAppendingPathComponent:@"Settings.bundle"];
    NSString *plistFile = [settingsPath stringByAppendingPathComponent:@"Root.plist"];

    NSDictionary *settingsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFile];
    NSArray *preferencesArray = [settingsDictionary objectForKey:@"PreferenceSpecifiers"];

    NSDictionary *item;

    NSString *textEntry_Key;
    NSString *readOnly_Key;


    for(item in preferencesArray)
    {
        //Get the key of the item.
        NSString *keyValue = [item objectForKey:@"Key"];

        //Get the default value specified in the plist file.
        id defaultValue = [item objectForKey:@"DefaultValue"];

        if([keyValue isEqualToString:@"textEntry_key"]){
            textEntry_Key = defaultValue;

        }

        NSLog(@"default value = %@",defaultValue);
        if([keyValue isEqualToString:@"readOnly_key"])
            readOnly_Key = defaultValue;



    }

    //Now that we have all the default values.
    //We will create it here.
    NSDictionary *appPrerfs = [NSDictionary dictionaryWithObjectsAndKeys:
                               textEntry_Key, @"textEntry_key",
                               readOnly_Key, @"readOnly_key",

                               nil];

    [[NSUserDefaults standardUserDefaults] registerDefaults:appPrerfs];
    [[NSUserDefaults standardUserDefaults] synchronize];

}

NSURL *url5 = [[NSURL alloc] initWithString:@"http://192.168.0.150/Nirmal/Service.asmx/searchParameterList"];
//NSURL *url5 = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%@/Service.asmx/searchParameterList"]];
NSMutableURLRequest* request6=[NSMutableURLRequest requestWithURL:url5];
[request6 setHTTPMethod:@"POST"]; 
[request6 setTimeoutInterval:10];
//NSURLResponse *response6=nil;
//  NSError *err6=nil;
    //NSData *data6=[[NSURLConnection sendSynchronousRequest:request6 returningResponse:&response6 error:&err6] retain];
    data2=[NSURLConnection sendSynchronousRequest:request6 returningResponse:nil error:nil];
    if(data2 == nil)
    {
        UIAlertView* alert = [[UIAlertView alloc]initWithTitle:@"Alert" message:@"The network is not available.\n Please check the Internet connection." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
        [alert release];

    }
    else
    {
        NSXMLParser *xmlParser5 = [[NSXMLParser alloc] initWithData:data2];

        //Initialize the delegate.
        SearchParameterDataParser *searchParameterDataParser = [[SearchParameterDataParser alloc] initSearchParameterDataParser];

        //Set delegate
        [xmlParser5 setDelegate:searchParameterDataParser];

        //Start parsing the XML file.
        @try {
            // **the leakage line**
            BOOL success1 = [xmlParser5 parse];


            if(success1)
                NSLog(@"No Errors");
            else
                NSLog(@"Error Error Error!!!");
        }
        @catch (NSException * e) {
            NSLog(@"Exception in parsing %@  %@",[e name], [e reason]);
        }
        //[xmlParser5 release];
        [searchParameterDataParser release];
        //[xmlParser5 release]; //leakage
    }

    [data2 release];

这是我的解析器类:

#import "SearchParameterDataParser.h"
#import "AppDelegate.h"
#import "SearchClass.h"

@implementation SearchParameterDataParser
-(SearchParameterDataParser *)initSearchParameterDataParser{
    [super init];
    appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    return self;
}

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

    if([elementName isEqualToString:@"SearchClass"]) {
        [appDelegate.tempArray release];
        appDelegate.tempArray = [[NSMutableArray alloc] init];
        appDelegate.aSearchClass = [[SearchClass alloc]init];
    }


    NSLog(@"Processing Element: %@", elementName);
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { 

    if(!currentElementValue){


        [currentElementValue release];
        currentElementValue = [[NSMutableString alloc] initWithString:string];
    }
    else
        [currentElementValue appendString:string];

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

}

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

    if([elementName isEqualToString:@"SearchClass"]){
        [appDelegate.tempArray addObject:appDelegate.aSearchClass];

        return;
    }
    else 
        [appDelegate.aSearchClass setValue:currentElementValue forKey:elementName];




//  [currentElementValue release];
    currentElementValue = nil;
}

- (void) dealloc {
    [super dealloc];    
    [aSearchClass release];
    [currentElementValue release];
    //[self release];

}
@end

我在代码中指定了泄漏线。

任何人都可以告诉我出了什么问题或者如何解决内存泄漏????????

2 个答案:

答案 0 :(得分:3)

这是非常混乱的,作为一个清理一点的建议,尝试将一些内存管理的东西移动到访问器方法 - 你的代码充满了-release方法。即,

而不是: -

if([elementName isEqualToString:@"SearchClass"]) {
    [appDelegate.tempArray release];
    appDelegate.tempArray = [[NSMutableArray alloc] init];
}

尝试: -

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

    appDelegate.tempArray = [NSMutableArray array];
}

其中

appDelegate有一个方法

- (void)setTempArray:(NSMutableArray *)value {

    if(value!=tempArray){
        [tempArray release];
        tempArray = [value retain];
    }
}

或者您可以使用@synthesized访问器方法自行保存编码。旁边的tempArray是一个实例变量的可怕名称。另请注意,每次创建新的tempArray时都会释放旧的tempArray - 最后一个实例何时清理?

这仍然不是很好,因为您的解析器类不应直接访问appDelegate中的实例变量。 Vardiables的tempArray和searchClass应该是私有的,但这不是重点,而是更多的设计问题。

url5在哪里发布?

这应该做什么?

if(!currentElementValue){
    [currentElementValue release];
}

如果不存在,则释放currentElementValue吗?

[data2 release];

您是否保留了数据2?

- (void) dealloc {
[super dealloc];    
    [aSearchClass release];
    [currentElementValue release];
    //[self release];

}

我认为aSearchClass是appDelegate上的一个实例变量?

这可能听起来像是挑剔,但如果让你的代码清楚并且你确切地知道发生了什么,那么追踪泄漏就容易得多。

答案 1 :(得分:1)

您需要同时发布url5xmlParser5,因为您已使用alloc分配它们。

您还应该警惕在属性上调用release,因为在@synthesize实例变量时创建的标准setter通常会在设置新值之前释放变量的先前值。