【问题标题】:GLKTextureLoader -textureWithCGImage:options:queue:completionHandler: malloc errorGLKTextureLoader -textureWithCGImage:options:queue:completionHandler: malloc 错误
【发布时间】:2012-07-08 12:38:48
【问题描述】:

我正在使用GLKTextureLoader 实例来异步加载纹理:

NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] 
                                                    forKey:GLKTextureLoaderOriginBottomLeft];
GLKTextureLoader *asyncLoader = [[GLKTextureLoader alloc] initWithSharegroup:sharegroup];
[asyncLoader textureWithCGImage:image
                        options:options
                          queue:NULL
              completionHandler:^(GLKTextureInfo *textureInfo, NSError *outError) {
                  if (outError) [ISDebugger logError:outError inMethod:_cmd];
                  GLuint textureName = [textureInfo name];
                  if (completionHandler) completionHandler(textureName);
              }];

第一次运行此代码时,它运行良好。但是第二次,我在控制台中收到malloc: *** error for object 0xa0cb3c0: pointer being freed was not allocated 警告。回溯似乎表明错误发生在GLKTextureLoader自己的工作线程中:

* thread #16: tid = 0x3003, 0x91a32c91 libsystem_c.dylib`malloc_error_break, stop reason = breakpoint 1.1
    frame #0: 0x91a32c91 libsystem_c.dylib`malloc_error_break
    frame #1: 0x91a32e07 libsystem_c.dylib`free + 358
    frame #2: 0x011f5003 CoreGraphics`image_provider_finalize + 29
    frame #3: 0x01b144b3 CoreFoundation`CFRelease + 291
    frame #4: 0x0118d96c CoreGraphics`CGImageBlockSetRelease + 76
    frame #5: 0x0154646c GLKit`-[GLKTexture dealloc] + 65
    frame #6: 0x02184e3d libobjc.A.dylib`_objc_rootRelease + 47
    frame #7: 0x01549da0 GLKit`+[GLKTextureLoader commonTextureWithCGImage:options:error:lock:eaglContext:] + 277
    frame #8: 0x0154b77e GLKit`__71-[GLKTextureLoader textureWithCGImage:options:queue:completionHandler:]_block_invoke_0 + 140
    frame #9: 0x0232b330 libdispatch.dylib`_dispatch_call_block_and_release + 15
    frame #10: 0x0232c439 libdispatch.dylib`_dispatch_worker_thread2 + 302
    frame #11: 0x919dfb24 libsystem_c.dylib`_pthread_wqthread + 346

显然,纹理加载器似乎过度释放了某些东西。我在这里做错了什么?


更新:

传递给方法的图像是这样获得的:

NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *imagePath = [bundlePath stringByAppendingPathComponent:imageFilename];
UIImage *uiImage = [UIImage imageWithContentsOfFile:imagePath];
CGImageRef image = [uiImage CGImage];

将图像生成更改为此可阻止错误发生:

UIImage *uiImage = [UIImage imageNamed:imageFilename];
CGImageRef image = [uiImage CGImage];

所以现在我想问题是为什么?我知道+imageNamed: 包含一些缓存行为,但为什么会影响这段代码?


更新 2:

使用[UIImage imageWithData:imageData] 创建图像时也是如此(发生崩溃)。似乎唯一的[UIImage imageNamed:imageName] 正在工作。任何想法为什么?

【问题讨论】:

  • image 来自哪里?
  • @borrrden 我已经用一些细节更新了这个问题。抱歉回复晚了。
  • 在您的完成块中,您有以下代码 if (completionHandler) completionHandler(textureName); 可能会发布此处调用的 completionHandler() 函数的源代码。
  • 纹理加载器在崩溃发生之前没有到达它自己的completionHandler 块(即if (outError) ... 行中的任何代码都没有运行过),所以我认为它不可能有关的。 my completionHandler 块中的代码因情况而异,但主要涉及将纹理绑定和绘制到 FBO(但就像我说的那样,它永远不会运行)。

标签: ios memory-management opengl-es glkit glktextureloader


【解决方案1】:

您正在使用异步方法来处理此项目。执行发布的可能不是 asyncLoader,而是其他东西。

如果您在本地将 image 声明为 UIImage,调用此 asyncLoader 以运行,然后立即退出当前的 stackFrame(即进行此调用的当前方法),则您传递的 UIImage 很可能在您执行某些操作之前已被释放在 asyncLoader 中使用它。 (如果 UIImage 被传入,但在调用堆栈帧中释放......或者如果它很弱并且持有它的引用的东西在 asyncLoader 运行之前将其删除,则会发生同样的事情)。

我建议从图像中创建一个强大的@property(并在您的 viewController 的 viewDidUnload 中将其设置为 nil),然后这个问题就会消失。

【讨论】:

  • 如果GLKTextureLoader 实例没有强烈捕获对传入图像的引用,我会感到惊讶。也许需要注意的是,您没有将UIImage 传递给方法,但是 CGImageRef... 对此的引用仍然依赖于 UIImage 闲逛吗?我将用关于图像来源的更多细节来更新我的问题,但在这里只想说我认为你对与图像引用所有权有关的错误是正确的。
猜你喜欢
  • 2013-11-04
  • 2011-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-13
  • 2014-03-29
相关资源
最近更新 更多