2009-09-14 168 views
19

我从调试器这样的信息:iPhone开发:指针被释放没有被分配

Pixture(1257,0xa0610500) malloc: *** error for object 0x21a8000: pointer being freed was not allocated 
*** set a breakpoint in malloc_error_break to debug 

,所以我做了追查了一下,得到:

(gdb) shell malloc_history 1257 0x21a8000

ALLOC 0x2196a00-0x21a89ff [size=73728]: thread_a0610500 |start | main | UIApplicationMain | GSEventRun | GSEventRunModal | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopDoObservers | CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) | CA::Transaction::commit() | CA::Context::commit_transaction(CA::Transaction*) | CALayerDisplayIfNeeded | -[CALayer _display] | CABackingStoreUpdate | backing_callback(CGContext*, void*) | -[CALayer drawInContext:] | -[UIView(CALayerDelegate) drawLayer:inContext:] | -[AvatarView drawRect:] | -[AvatarView overlayPNG:] | +[UIImageUtility createMaskOf:] | UIGraphicsGetImageFromCurrentImageContext | CGBitmapContextCreateImage | create_bitmap_data_provider | malloc | malloc_zone_malloc

我真的不明白wh在我做错了。这里的[UIImageUtility createMaskOf:]函数的代码:

+ (UIImage *)createMaskOf:(UIImage *)source { 
    CGRect rect = CGRectMake(0, 0, source.size.width, source.size.height); 
    UIGraphicsBeginImageContext(CGSizeMake(source.size.width, source.size.height)); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    CGContextTranslateCTM(context, 0, source.size.height); 
    CGContextScaleCTM(context, 1.0, -1.0); 

    UIImage *original = [self createGrayCopy:source]; 

    CGContextRef context2 = CGBitmapContextCreate(NULL, source.size.width, source.size.height, 8, 4 * source.size.width, 
                CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipLast); 
    CGContextDrawImage(context2, CGRectMake(0, 0, source.size.width, source.size.height), original.CGImage); 
    CGImageRef unmasked = CGBitmapContextCreateImage(context2); 

    const float myMaskingColorsFrameColor[6] = { 1,256,1,256,1,256 }; 
    CGImageRef mask = CGImageCreateWithMaskingColors(unmasked, myMaskingColorsFrameColor); 

    CGContextSetRGBFillColor (context, 256,256,256, 1); 
    CGContextFillRect(context, rect); 
    CGContextDrawImage(context, rect, mask); 

    UIImage *whiteMasked = UIGraphicsGetImageFromCurrentImageContext(); 

    UIGraphicsEndImageContext(); 

    return whiteMasked; 
} 

之前调用其他自定义功能如下:

- (UIImage *)overlayPNG:(SinglePart *)sp { 
    NSLog([sp description]); 
    // Rect and context setup 
    CGRect rect = CGRectMake(0, 0, sp.image.size.width, sp.image.size.height); 
    NSLog(@"%f x %f", sp.image.size.width, sp.image.size.height); 

    // Create an image of a color filled rectangle 
    UIImage *baseColor = nil; 
    if (sp.hasOwnColor) { 
      baseColor = [UIImageUtility imageWithRect:rect ofColor:sp.color]; 
    } else { 
     SinglePart *facePart = [editingAvatar.face.partList objectAtIndex:0]; 
     baseColor = [UIImageUtility imageWithRect:rect ofColor:facePart.color]; 
    } 

    // Crete the mask of the layer 
    UIImage *mask = [UIImageUtility createMaskOf:sp.image]; 
    mask = [UIImageUtility createGrayCopy:mask]; 

    // Create a new context for merging the overlay and a mask of the layer 
    UIGraphicsBeginImageContext(CGSizeMake(sp.image.size.width, sp.image.size.height)); 
    CGContextRef context2 = UIGraphicsGetCurrentContext(); 

    // Adjust the coordinate system so that the origin 
    // is in the lower left corner of the view and the 
    // y axis points up 
    CGContextTranslateCTM(context2, 0, sp.image.size.height); 
    CGContextScaleCTM(context2, 1.0, -1.0); 

    // Create masked overlay color layer 
    CGImageRef MaskedImage = CGImageCreateWithMask (baseColor.CGImage, mask.CGImage); 

    // Draw the base color layer 
    CGContextDrawImage(context2, rect, MaskedImage); 

    // Get the result of the masking 
    UIImage* overlayMasked = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    UIGraphicsBeginImageContext(CGSizeMake(sp.image.size.width, sp.image.size.height)); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    // Adjust the coordinate system so that the origin 
    // is in the lower left corner of the view and the 
    // y axis points up 
    CGContextTranslateCTM(context, 0, sp.image.size.height); 
    CGContextScaleCTM(context, 1.0, -1.0); 

    // Get the result of the blending of the masked overlay and the base image 
    CGContextDrawImage(context, rect, overlayMasked.CGImage); 

    // Set the blend mode for the next drawn image 
    CGContextSetBlendMode(context, kCGBlendModeOverlay); 

    // Component image drawn 
    CGContextDrawImage(context, rect, sp.image.CGImage); 

    UIImage* blendedImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    CGImageRelease(MaskedImage); 

    return blendedImage; 
} 

回答

27

我有同样的问题,有很多相同的症状:被释放

  • 指针没有被分配错误
  • 升级到3.2的Xcode
  • 错误代码为发生图像

如果我将构建目标更改为3.1,则模拟器中的错误将消失。如果我在设备上运行代码,则不会显示错误。可能是3.0中的一个错误

我的建议是以3.1作为目标进行测试,如果需要,可以为3.0版本构建版本,而不用担心错误,因为它们不会在设备上发生。

+0

它看起来像3.0中的一个bug,因为我也有这个问题,当我将目标设置为3.1时,它就消失了。 – lucius 2010-01-08 03:23:16

+0

只是说我有完全相同的问题,设置3.1也解决了我的情况。谢谢 – Andy 2010-01-14 21:07:39

+0

另一个“我也是”。看起来像3.0模拟器中的一个错误。 3.1+在模拟器和3.0在设备上测试都很好。 – 2010-03-11 04:48:12

22

它看起来像你有一个损坏的内存错误,并且很可能是在此码。损坏的内存错误是我的第二个最有趣的错误,部分原因是它们通常是非确定性的,并且实际的错误命中之后,症状(又名崩溃)通常发生在之后。

主要有两种类型的内存错误的:

  1. 分配比你更自由。
  2. 超过您的分配空间。

在这种情况下,它看起来像你释放了太多,这是更容易看到的情况下(B/C它可以先崩溃),但更难追查。

这里是一个战略,你可以用它来帮助找到一个额外的释放操作:

  • 关掉你的一些释放操作的。
  • 看看是否仍然发生崩溃。

理想情况下,您可以找到一个单独的释放命令,当它被移除时,将允许您的代码正常工作。如果这对您的代码库很实用,那么尝试二进制搜索方法可能会很有用。如果它是一个很大的代码库,希望你使用版本控制,你可以尝试着重于最近的差异。

请记住,在这里可以通过几种不同的方式调用释放。最有可能的是,您在对象上调用releaseautorelease。也有可能你明确地打电话给dealloc(尽管这通常是个错误)。当然,你甚至可以直接明确地拨打free

一旦你摆脱了额外的释放,最好也检查内存泄漏(又称额外分配)。你可以使用仪器和其他工具来做到这一点。开始的一个好地方是在iPhone开发指南中阅读Finding Memory Leaks

加入:在释放它并完成使用后,最好设置一个指向nil的指针。这样,如果您稍后致电[objectPtr release];,它将不会执行任何操作。

(PS顺便说一句,我的#1最好玩的错误类型是mutlithreaded代码内存损坏。我有那些曾经在数百万行的代码库之一。)

+0

它你认为probabl是真实的,也是因为我发布的这条消息与应用程序崩溃不对应,它只是在调试控制台(并减缓应用程序)写入随机fashon中,有时会给我2个,有时甚至是4,有时甚至没有消息...无论如何,我会尽量按照你的指示,看看我能不能到达任何地方。如果我没有,也许我可以发布更多的代码,你可以帮我找到问题? – w4nderlust 2009-09-15 17:52:44

+0

您可以发布,但在这里没有关于详细的逐行调试的承诺。 Stackoverflow更多的是关于大图问题或者快速特定问题,而不是费时费力的问题,因为最后一种问题对其他人来说是最不实用的。此外,为免费的陌生人做了很多工作;) – Tyler 2009-09-15 18:11:32

+0

我删除了在第一个消息出来之前加载的所有类中的每个发布版本调用。我根本没有结果。我会告诉你前面的函数调用我所展示的函数,希望问题出现在那里。 (顺便说一句,我必须说一个有趣的事情:应用程序没有这个错误,因为我更新到雪豹和xcode 3.2 ...没有改变这条线的错误出来) – w4nderlust 2009-09-15 19:23:36

3

虽然可能不是原因的崩溃,通过不使用CFRelease(),CFImageRelease()等释放context2,unmaskedmask核心基础对象来泄漏内存。

+0

添加了CGContextRelease()和CGImageRelease(),谢谢你的建议;) – w4nderlust 2009-09-15 17:16:22

0

我对以下代码有同样的问题。

-(void)adjustImageToImageView:(UIImage*)img{ 

float numPixels = 100; 
float radius = 5; 
UIGraphicsBeginImageContext(CGSizeMake(numPixels, numPixels)); 
CGContextRef c = UIGraphicsGetCurrentContext(); 

CGContextBeginPath(c); 
CGContextMoveToPoint (c, numPixels, numPixels/2); 
CGContextAddArcToPoint(c, numPixels, numPixels, numPixels/2, numPixels, radius); 
CGContextAddArcToPoint(c, 0,   numPixels, 0,   numPixels/2, radius); 
CGContextAddArcToPoint(c, 0,   0,   numPixels/2, 0,   radius); 
CGContextAddArcToPoint(c, numPixels, 0,   numPixels, numPixels/2, radius); 
CGContextClosePath(c); 

CGContextClip(c); 

[img drawAtPoint:CGPointZero]; 
UIImage *converted = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
self.imageView.image = converted; } 

我从开源的Twitterfon应用程序中取得了这个功能。

当我试图解决这个问题,我试图改变最后一行

self.imageView.image = [converted retain] 

而且,在控制台停止错误消息。我将很快检查这个漏洞,看看发生了什么。

+0

我刚跑漏。该应用程序泄露UIImage。所以这绝对不是一个解决方案!有趣的是malloc错误被这个压制了。 – infiniteloop 2009-09-24 15:17:06

0

我只是想确认,再次,我已经是越来越:被释放

指针没有被分配

错误,如果我改变我的目标操作系统它走了3.1而不是3.0

+0

是的,我也一样。 'UIGraphicsGetImageFromCurrentImageContext()'应该返回一个自动发布的UIImage,但它似乎是双重autoreleasing它,只在3.0模拟器中,并且只使用Xcode 3.2 – 2010-03-19 17:44:53

0

我在我的代码中遇到了同样的错误。我感到困惑的是,我的应用程序在OS 3.0中工作没有任何问题,直到我对与CGImage *东西无关的代码进行了小小的修改。但是一旦它开始失败,那么它不会崩溃。当我切换到3.1时,一切都恢复正常。我将错误缩小为CGImageRelease()调用。无论是移除该行还是在生成的UIImage上添加保留都解决了问题 - 尽管这是一个无法解决的问题,因为该应用会泄漏内存。

我试过用仪器使用NSZombie。这没有帮助 - 应用程序崩溃没有任何僵尸被发现。此外,苹果自己的示例应用程序(如TheElements)不会崩溃,但会使用与我的应用程序相同的EXACT代码。所以,我很难接受框架中存在的问题。目前,我正在转向3.1并继续前进。

0

这可能只是我,但你不能做到以下几点?

UIImage *whiteMasked = UIGraphicsGetImageFromCurrentImageContext(); 

UIGraphicsEndImageContext(); 

return whiteMasked; 

whiteMasked是分配在该函数的堆栈上,并且在它返回指针后不再有效?或者我错过了什么?如果您使用返回的UIImage *,则不能保证仍然存在。 (这将是一个命中和错过)。你不需要分配一个UIImage *,然后在返回之前自动释放它?

+0

Cocoa/Objective-C中的对象始终分配在堆上,从不在堆栈上。存储在'whiteMasked'中的指针至少在当前自动释放池被排空之前是有效的,直到事件循环结束为止。在这个函数中使用它很好,也可以返回它。如果我们打算保存它并稍后使用相同的图像(例如,在一个实例变量中),我们只需要制作一个副本。 – benzado 2010-06-04 05:55:53

相关问题