2013-09-05 1 views
0

В настоящее время я использую GLKit для создания рисунка OpenGL. Я создал обычный UIViewController, а затем добавил подкласс GLKViewController внутри контейнера, чтобы сделать мой чертеж. Хотя сначала все работает нормально, если я позволяю моей программе работать в течение определенного периода времени (возможно, 15-30 минут), в конце концов он сбой и дает мне следующую ошибку.Создание автореализованного объекта внутри цикла запуска GLKViewController вызывает ошибку malloc

malloc: *** mmap(size=2097152) failed (error code=12) 
*** error: can't allocate region 
*** set a breakpoint in malloc_error_break to debug 

Так что я включил malloc_error_break точки останова и трассировки стека указывает на следующий код.

-(NSArray*)meshes:(NSArray *)meshes sortedFromFrontToBack:(BOOL)sortedFromFrontToBack 
{ 
    NSMutableArray *sortedMeshes = meshes.mutableCopy; 
    [sortedMeshes sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { 
     DSNode *mesh1 = obj1; 
     DSNode *mesh2 = obj2; 
     GLKVector3 depth1 = isnan(mesh1.boundingSphere.radius) ? mesh1.transformationState.position : mesh1.boundingSphere.center; 
     GLKVector3 depth2 = isnan(mesh2.boundingSphere.radius) ? mesh2.transformationState.position : mesh2.boundingSphere.center; 

     GLKMatrix4 mesh1ToCameraSpace = [mesh1 nodeToOtherNodeTransform:self]; 
     GLKMatrix4 mesh2ToCameraSpace = [mesh2 nodeToOtherNodeTransform:self]; 

     GLKVector3 depth1InCameraSpace = GLKMatrix4MultiplyVector3WithTranslation(mesh1ToCameraSpace, depth1); 
     GLKVector3 depth2InCameraSpace = GLKMatrix4MultiplyVector3WithTranslation(mesh2ToCameraSpace, depth2); 


     NSNumber *n1 = [NSNumber numberWithFloat:depth1InCameraSpace.z]; 
     NSNumber *n2 = [NSNumber numberWithFloat:depth2InCameraSpace.z]; /* Breakpoint triggered here */ 

     if(sortedFromFrontToBack) 
     { 
      return [n2 compare:n1]; 
     } 
     return [n1 compare:n2]; 
    }]; 

    return sortedMeshes; 
} 

Как я заметил, то [NSNumber numberWithFloat:] вызов бросает ошибку таНос. Этот метод вызывается один раз каждый кадр из моего метода drawInRect GLKViewController. По сути, у меня есть класс, который отслеживает мои камеры и сетки, которые будут нарисованы OpenGL, и он сортирует их в пространстве камеры от переднего к заднему для непрозрачных сеток или назад к переднему для прозрачного перед их рисованием.

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect 
{ 
    glClearColor(self.clearColor.r, self.clearColor.g, self.clearColor.b, self.clearColor.a); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    DSDirector *director = [DSDirector sharedDirector]; 

    for(DSMesh *mesh in director.opaqueMeshes) 
    { 
     [mesh draw]; 
    } 

    /* The director class keeps track of my scene's cameras and meshes and calls the above method to return the scene's transparent meshes properly sorted */ 
    for(DSMesh *mesh in director.transparentMeshes) 
    { 
     [mesh draw]; 
    } 
} 

Из того, что я прочитал, то autorelease пул должен стекать в конце каждого цикла выполнения, так что я не думаю, что создание кучу autoreleased объектов каждый кадр является проблемой, все они должны получить покраснение каждого кадра. Я профилировал свою программу и проверял любые утечки и не могу найти, и я тоже использую ARC, что должно минимизировать риск. Когда я просматриваю его, общая сумма байтов в байтах никогда не увеличивается, хотя общие байты быстро растут, и никаких утечек не обнаружено. Кроме того, didReceiveMemoryWarning никогда не срабатывает. Я в тупике.

ответ

0

Итак, я думаю, что я понял, что происходит. В какой-то момент я включил NSZombies, а затем забыл об этом, и поэтому все мои объекты, которые я ожидал освободить, на самом деле все еще висели. При профилировании в Инструментах зомби нельзя считать живыми, поэтому я не мог понять, почему у меня, казалось бы, не хватило памяти, когда количество живых байтов не поднималось. Однако, когда я обновился до XCode 5, новый манометр показал, что я быстро собираю память, а затем, когда я зашел в «Инструменты», утечка была закрыта предупреждением, в котором говорилось, что это не сработает должным образом, поскольку NSZombies были включены. Итак, я отключил зомби, и теперь мое использование памяти остается постоянным, как и ожидалось.

0

Что-то плохое в отношении создания NSNumber является причиной вашей ошибки malloc. Тестирование с помощью инструментов может помочь найти настоящего преступника.

Однако вы делаете две вещи, которые вам не нужны, поэтому есть шанс, что устранение их может помочь в вашей проблеме.

Во-первых, вам не нужно обертывать float s в NSNumber, чтобы сравнить их. Основные сравнения и математические операторы работают очень хорошо, и не требуют дополнительного времени или памяти для создания объекта:

if (depth1InCameraSpace.z < depth2InCameraSpace.z) 
    return NSOrderedAscending; 
else if (depth1InCameraSpace.z > depth2InCameraSpace.z) 
    return NSOrderedDescending; 
else 
    return NSOrderedSame; 

Во-вторых, Плитка на основе Отложенный стратегии рендеринга реализованы аппаратными средствами GPU на IOS устройств делает свой собственный оптимизация удаления скрытых поверхностей - сортировка непрозрачной геометрии спереди назад является излишней, поэтому все, что она делает, - это временное процессорное время. (Есть приличное объяснение этого в OpenGL ES Hardware Platform Guide for iOS.) Вы все равно должны сортировать полупрозрачную геометрию назад (и нарисовать ее после непрозрачной геометрии) для правильного смешивания.

+0

Хм, похоже, что вы правы, автореализованные объекты не являются проблемой. Позаботился о тех вещах, которые вы указали, и я все еще получаю ошибку в malloc, просто ломаясь в другом месте.На этот раз я делаю некоторое руководство KVO свойства GLKVector3, а трассировка стека заканчивается на строке didChangeValueForKey: с той же самой ошибкой malloc mmap. Поскольку это похоже на проблему с памятью, я смотрел на Allocations/Leaks in Instruments, и все выглядит отлично, никаких утечек, количество живых байтов никогда не растет, просто не понимайте, куда идти оттуда. – Devin