0

我已经开发了我的 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

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

谁能告诉我出了什么问题或我该如何解决内存泄漏???????

4

2 回答 2

3

这很混乱,作为清理工作的建议,尝试将一些内存管理内容移至访问器方法 - 您的代码中到处都是 -release 方法。IE,

代替:-

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 中的实例变量。变量 tempArray 和 searchClass 应该是私有的,但这不是重点,更多的是设计问题。

url5 在哪里发布?

这应该做什么?

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

如果 currentElementValue 不存在则释放它?

[data2 release];

你保留了data2吗?

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

}

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

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

于 2009-11-04T12:01:51.563 回答
1

您需要同时释放url5and xmlParser5,因为您已经使用alloc.

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

于 2009-11-04T12:07:27.620 回答