简体   繁体   English

如何修复 Objective-C 中的内存泄漏?

[英]How to fix the memory leaks in Objective-C?

I built a simple app which gets the reports from HockeyApp.我构建了一个简单的应用程序,它从 HockeyApp 获取报告。 However when I run the app with the memory leak instruments, it showed there was a memory leak when I perform the getReport action.但是,当我使用内存泄漏工具运行应用程序时,它显示当我执行 getReport 操作时存在内存泄漏。 I couldn't understand all the information shown in the instrument.我无法理解仪器中显示的所有信息。

Here is the button action method which causes the memory leak:这是导致内存泄漏的按钮操作方法:

- (IBAction)getReports:(id)sender {

//initialize url that is going to be fetched.
NSURL *url = [NSURL URLWithString:@"https://rink.hockeyapp.net/api/2/apps/APP_ID/crash_reasons"];

//initialize a request from url
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request addValue:tokenReceived forHTTPHeaderField:@"X-HockeyAppToken"];

[request setHTTPMethod:@"GET"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

//initialize a connection from request
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
self.getReportConnection = connection;

}


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)data{

    if (connection==getReportConnection) {

     [self.receivedData appendData:data];

     NSLog(@"data is %@",data);

    NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    NSError *e = nil;
    NSData *jsonData = [responseString dataUsingEncoding:NSUTF8StringEncoding];

    NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:jsonData options: NSJSONReadingMutableContainers error: &e];
    NSLog(@"login json is %@",JSON);
     NSLog(@"reason json is %@",JSON[@"reason"]);

    [JSON[@"crash_reasons"] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {


        [reportArray addObject:obj[@"reason"]];
         NSLog(@"index = %lu, Object For title Key = %@", (unsigned long)idx, obj[@"reason"]);
    }];

    NSError *error = nil;
    NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:jsonData
                                                         options:kNilOptions error:&error];

    if (error != nil) {
        NSLog(@"Error parsing JSON.");
    }
    else {
        NSLog(@"Array: %@,array count is %d", jsonArray,jsonArray.count);
    }

   // [reportArray addObject:[jsonArray objectAtIndex:0]];

    if (JSON!=NULL) {
        UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Reports succesfully retrieved" message:@"" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
        [alert show];
    }

       }
}

 // This method receives the error report in case of connection is not made to server.
 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{

UIAlertView *errorAlert=[[UIAlertView alloc]initWithTitle:@"Wrong Login" message:nil delegate:self cancelButtonTitle:@"ok" otherButtonTitles: nil];
[errorAlert show];
NSLog(@"error is %@",error);
}

// This method is used to process the data after connection has made successfully.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{

}

I see that the memory leak occurs just before the alert view appears in the didRecieveData method.我看到内存泄漏发生在didRecieveData方法中出现警报视图之前。

Here is the screenshot of the memory leak instrument showing memory leak:这是显示内存泄漏的内存泄漏工具的屏幕截图:

在此处输入图片说明

I couldn't understand which part of the code causes the memory leak.我无法理解代码的哪一部分导致内存泄漏。 Can anyone tell me how to identify the part of code that causes the memory leak with the leak instrument?谁能告诉我如何使用泄漏工具识别导致内存泄漏的代码部分?

Edit: When I run the app on the simulator, the instrument didnt show any memory leak:编辑:当我在模拟器上运行应用程序时,仪器没有显示任何内存泄漏:

Here is the screenshot:这是屏幕截图:在此处输入图片说明

Again When I run the app on device, the instrument showed me the memory leak:再次当我在设备上运行应用程序时,仪器向我显示了内存泄漏:在此处输入图片说明

I looked into the leaks section and I found NSmutableArray is causing the leak:我查看了泄漏部分,发现NSmutableArray导致泄漏: 在此处输入图片说明在此处输入图片说明

I used only one NSMutableArray in my code.我在代码中只使用了一个NSMutableArray I declared it in .h file:我在.h文件中声明了它:

@property (nonatomic,strong) NSMutableArray *reportArray;

and allocated it in viewDidLoad :并在viewDidLoad分配它:

reportArray=[[NSMutableArray alloc]init];

and loaded it in didRecieveData :并将其加载到didRecieveData

 [reportArray addObject:obj[@"reason"]];

Stacktrace snapshots:堆栈跟踪快照:

在此处输入图片说明在此处输入图片说明在此处输入图片说明

Try this:尝试这个:

reportArray = [[[NSMutableArray alloc] init] autorelease];

in your connectionDidFinishLoading: and connection:didFailWithError: methods set在您的connectionDidFinishLoading:connection:didFailWithError:方法中设置

reportArray = nil

and finally in Project > Build Phases > Compile Sources add -fno-objc-arc as compiler flag for this file (edited, sorry) .最后在Project > Build Phases > Compile Sources添加-fno-objc-arc作为此文件的编译器标志(已编辑,抱歉) Then click Product menu >Analyze (command + shift + B) again and check if the memory leak still occurs.然后再次单击产品菜单>分析(command + shift + B)并检查是否仍然存在内存泄漏。

It is possible it is Apple's leak -- sure looks like it is coming from UIAlertView / UIAlertConnection.这可能是 Apple 的泄漏——看起来它来自 UIAlertView/UIAlertConnection。 You might try implementing the alert using UIAlertConnection and see if it goes away -- Apple may not have tested the back-compatible UIAlertView implementation as much.您可以尝试使用 UIAlertConnection 实现警报并查看它是否消失——Apple 可能没有对向后兼容的 UIAlertView 实现进行太多测试。

It won't show up in leaks, but be aware that NSURLConnection retains its delegate, and in your case you have your delegate retaining the NSURLConnection it looks like.它不会出现在泄漏中,但请注意 NSURLConnection 保留其委托,在您的情况下,您的委托保留了 NSURLConnection 它看起来像。 That should be a retain loop if I'm not mistaken.如果我没记错的话,那应该是一个保留循环。 Be sure to break it (nil out the delegate, or nil out the connection on your controller) when the connection finishes or fails.当连接完成或失败时,一定要断开它(nil out the delegate,或者nil out the connection on your controller)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM