【问题标题】:Objective C: EXC_BAD_ACCESS when generating a UIImage目标 C:生成 UIImage 时的 EXC_BAD_ACCESS
【发布时间】:2010-08-25 22:23:08
【问题描述】:

我有一个基于一系列图层生成图像的视图。我有背景图像,缩略图,最后是叠加层。它共同构成了一个有凝聚力的展示。

它似乎实现了一个梦想,除非它没有。似乎没有任何原因,在生成了 8 到 20 个图像之后,我在下面的指定行上得到了一个 EXC_BAD_ACCESS。我已经通过内存泄漏工具和分配工具运行它,它没有消耗大量内存,也没有泄漏。我完全被难住了。

以下是相关代码:

- (UIImage *)addLayer:(UIImage *)layer toImage:(UIImage *)background atPoint:(CGPoint)point {
  CGSize size = CGSizeMake(240, 240);
  UIGraphicsBeginImageContext(size);

  [background drawAtPoint:CGPointMake(0, 0)];  // <--- error here
  [layer drawAtPoint:point];

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

  return result;
}


// Build the layered image -- thingPage onto thingBackground,
// then the screenshot on that, then the thingTop on top of it all.
// thingBackground, thingPage and thingTop are all preloaded UIImages.
-(UIImage *)getImageForThing:(Thing *)t {
  [self loadImageCacheIfNecessary];

  if (!t.screenshot) {
    return [UIImage imageNamed:@"NoPreview.png"];
  } else {
    UIImage *screenshot = t.screenshot;
    UIImage *currentImage = [self addLayer:thingPage toImage:thingBackground atPoint:CGPointMake(0, 0)];
    currentImage = [self addLayer:screenshot toImage:currentImage atPoint:CGPointMake(39, 59)];
    currentImage = [self addLayer:thingTop toImage:currentImage atPoint:CGPointMake(0, 1)]; 

    return currentImage;
  }
}

我找不到哪里出了问题,为此我已经把头发扯了几个小时。这是系统中最后一个已知的错误,所以你可以想象我修复它有多着急! :-)

提前感谢您的帮助。

【问题讨论】:

  • 打开 NSZombieEnabled 以查看您的指针可能出错的地方怎么样?
  • 我已经打开了 NSZombieEnabled,现在可以确定我正在向已释放的实例发送消息。但是,我不确定它在哪里或为什么被释放。
  • 你能分辨出哪个addLayer:... 调用它崩溃了吗?在此方法的 3 个调用周围添加 NSLog 调用。
  • 我运行了 4 次,每次都是在第一次调用 addLayer 时:UIImage *currentImage = [self addLayer:thingPage toImage:thingBackground atPoint:CGPointMake(0, 0)];
  • 找到了!在loadImageCacheIfNecessary 方法中缺少retain 调用。感谢所有参与的人! :-)

标签: iphone objective-c ipad uiimage


【解决方案1】:

就我而言,我总是使用 -(void)drawInRect: 而不是 -(void)drawAtPoint:


CGRect rtDraw;
rtDraw.origin = CGPointZero;
rtDraw.size = size;
[background drawInRect:rtDraw];
[layer drawInRect:rtDraw];

还有.... UIGraphicsBeginImageContext(size) 和 UIGraphicsEndImageContext() 的绘制方法不是线程安全的。 这些函数将使用由系统管理的堆栈结构推送或弹出上下文。

【讨论】:

  • 不幸的是,这会产生完全相同的错误。不过谢谢! :-)
【解决方案2】:

EXC_BAD_ACCESS 几乎总是由于访问一个已经被释放的对象。在您的代码中,这似乎是t.screenshot。检查Thingscreenshot 属性返回的对象的创建(如果它是实例变量则保留)。

【讨论】:

    【解决方案3】:

    事实证明,错误不在我发布的代码中,而是在我对thingBackgroundthingPagethingTop 图像的缓存中。我没有留住他们。这是缺少的代码,已修复:

    -(void)loadImageCacheIfNecessary {
      if (!folderBackground) {
        thingBackground = [[UIImage imageNamed:@"ThingBack.png"] retain];
      }
      if (!folderPage) {
        thingPage = [[UIImage imageNamed:@"ThingPage.png"] retain];
      }
      if (!folderTop) {
        thingTop = [[UIImage imageNamed:@"ThingTop.png"] retain];
      }
    }
    

    我承认我仍然对 Objective C 中的全部保留/释放/自动释放内容感到不满意。希望它很快会在某一天消失。 :-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-10
      • 1970-01-01
      • 2017-12-14
      相关资源
      最近更新 更多