GLKTextureLoader -textureWithCGImage: опции: очередь: завершение Хендлер: ошибка malloc

Я использую 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] работает. Есть идеи почему?

1 ответ

Вы используете асинхронный метод для обработки этого элемента. скорее всего, выполняя релиз, не asyncLoader, а что-то другое.

если вы объявили изображение как UIImage локально, вызвали этот asyncLoader для запуска, а затем сразу же вышли из текущего стека Frame (т. е. текущего метода, который делает этот вызов), переданный вами UIImage, вероятно, будет выпущен до того, как вы что-то сделаете с ним в asyncLoader. (то же самое произойдет, если UIImage был передан, но освобожден в вызывающем стековом фрейме... или если он слабый, и объект, который содержит ссылку на него, удаляет его перед запуском asyncLoader).

я бы предложил сделать сильный @property из изображения (и установить его равным nil в viewDidUnload вашего viewController), и тогда эта проблема должна исчезнуть.

Другие вопросы по тегам