【问题标题】:How to release memory in objective-c?如何在objective-c中释放内存?
【发布时间】:2015-06-25 04:47:14
【问题描述】:

我正在我的应用程序中开发 Gps 地图概念。在这里我在我的代码中发现内存泄漏我最终解决了一些内存泄漏这里三个内存泄漏来了我不知道如何解决这个问题请指导我。这是我的代码库和屏幕截图

https://drive.google.com/file/d/0B14zCKcRh39AWm1QNTFMejNqOGc/view?usp=sharing

https://drive.google.com/file/d/0B14zCKcRh39AcmhyM3R3c1ZrZE0/view?usp=sharing

 -(NSArray *)decodePolyLine: (NSMutableString *)encoded {
        [encoded replaceOccurrencesOfString:@"\\\\" withString:@"\\"
                                    options:NSLiteralSearch
                                      range:NSMakeRange(0, [encoded length])];
        NSInteger len = [encoded length];
        NSInteger index = 0;
        NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
        NSInteger lat=0;
        NSInteger lng=0;
        while (index < len) {
            NSInteger b;
            NSInteger shift = 0;
            NSInteger result = 0;
            do {
                b = [encoded characterAtIndex:index++] - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
            lat += dlat;
            shift = 0;
            result = 0;
            do {
                b = [encoded characterAtIndex:index++] - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
            lng += dlng;
            NSNumber *latitude = [[[NSNumber alloc] initWithFloat:lat * 1e-5] autorelease];
            NSNumber *longitude = [[[NSNumber alloc] initWithFloat:lng * 1e-5] autorelease];
            printf("[%f,", [latitude doubleValue]);
            printf("%f]", [longitude doubleValue]);
            CLLocation *loc = [[[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]] autorelease];
            [array addObject:loc];
        }

        return array;
    }

    -(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t {
        NSString* saddr = [NSString stringWithFormat:@"%f,%f", f.latitude, f.longitude];
        NSString* daddr = [NSString stringWithFormat:@"%f,%f", t.latitude, t.longitude];

        NSString* apiUrlStr = [NSString stringWithFormat:@"http://maps.google.com/maps?output=dragdir&saddr=%@&daddr=%@", saddr, daddr];
        NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
        NSLog(@"api url: %@", apiUrl);
        NSError *error;
        NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:&error];
        NSString* encodedPoints = [apiResponse stringByMatching:@"points:\\\"([^\\\"]*)\\\"" capture:1L] ;

        return [self decodePolyLine:[encodedPoints mutableCopy]];


}




-(void) updateRouteView {
    CGContextRef context =  CGBitmapContextCreate(nil,
                                                  routeView.frame.size.width, 
                                                  routeView.frame.size.height, 
                                                  8, 
                                                  4 * routeView.frame.size.width,
                                                  CGColorSpaceCreateDeviceRGB(),
                                                  (kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast) | (kCGBitmapByteOrderMask & kCGBitmapByteOrderDefault)) ;


    CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
    CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
    CGContextSetLineWidth(context, 3.0);

    for(int i = 0; i < routes.count; i++) {
        CLLocation* location = [routes objectAtIndex:i];
        CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView];

        if(i == 0) {
            CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
        } else {
            CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
        }
    }

    CGContextStrokePath(context);

    CGImageRef image = CGBitmapContextCreateImage(context);
    UIImage* img = [UIImage imageWithCGImage:image];
    CGContextRelease(context);
    routeView.image = img;
   // CGContextRelease(context);



}

【问题讨论】:

  • 是的,我正在使用 ARC @MidhunMP
  • 您是否分析过您的应用程序的分配和内存泄漏?您能否从分析中提供任何其他信息来指示内存泄漏出现的位置?
  • 我已经在上面的两个屏幕截图中添加了这些信息。
  • @DerekLee 你只要看看上面的链接就明白了。

标签: ios objective-c memory-management memory-leaks


【解决方案1】:

如果使用 ARC,则不需要管理内存。

如果您不这样做,请使用[object release]

强烈建议您在继续阅读之前阅读Managing Memory in Objective-C

【讨论】:

  • 我已经添加了 ARC。这里我不知道如何释放该对象。
  • @Ram 那么你不需要发布任何东西。
  • 即使使用 ARC,您也必须始终考虑内存管理。
【解决方案2】:

对于屏幕截图 #2,您似乎没有释放 CGImageRef 对象。为此,要清理它,您应该使用:

CGImageRelease(image); 

...当您使用完 CGImageRef。

更多信息(以及它与 CFRelease 的区别)可以在这个问题上找到:Releasing CGImage (CGImageRef) 请注意,即使您使用的是 ARC,在使用任何基于 C 的 API 时也需要小心,尤其是当您将它们与一些 Obj-C 对象混合在一起时。

对于第一个屏幕截图和您发布的代码很难说,因为逻辑非常复杂,但是我建议如果您使用 ARC,那么我会质疑是否在所有初始化程序上使用“自动释放”是真的很有必要。当我尝试在 ARC 项目中使用“autorelease”时,它甚至不会让我这样做:Xcode 给出消息“ARC 禁止显式发送 'autorelease' 的消息。”您可能需要确认您确实为此项目启用了 ARC。

如果有帮助,此问题讨论为您的项目启用 ARC:How to enable/disable ARC in an xcode project?


编辑新添加的屏幕截图

此屏幕截图的 Xcode 错误消息非常清楚地表明问题出在哪里。当调用“CGColorSpaceCreateDeviceRGB”时,这将创建一个您负责明确释放的对象。

如果您查看有关 CGColorSpaceCreateDeviceRGB 的文档,您会发现文档“返回”描述中也说明了这一点:

因此,您需要在创建 CGContextRef 之前调用“CGColorSpaceCreateDeviceRGB”,并且需要在使用 CGColorSpaceRelease 完成上下文后释放它:

CGColorSpaceRef myColorSpaceRef = CGColorSpaceCreateDeviceRGB();

CGContextRef myContext = CGBitmapContextCreate(...);

...

CGContextRelease(myContext);

CGColorSpaceRelease(myColorSpaceRef);

【讨论】:

  • 首屏拍摄方案?
  • 我建议您确认已将 ARC 正确添加到您的项目中 - 首先将您的项目转换为 ARC 项目,然后执行后续步骤(请注意,这不是从构建阶段 >> 编译源代码完成的) .
  • 是的,我同意,如果这些自动释放消息没有产生警告,那么 ARC 可能没有打开,至少对于这个类来说,如果不是整个目标的话。而且,如果您认为 ARC 已启用而实际上并未启用,那么我希望您的代码确实会非常泄漏。
  • 刚刚我又添加了一个链接,看到我忘记分享这些链接了。
  • 更新答案以包含基于您新添加的屏幕截图的其他信息。
猜你喜欢
  • 1970-01-01
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多