2013-09-05 38 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:]调用引发malloc错误。这个方法每次从我的GLKViewController的drawInRect方法调用一次。基本上,我有一个类来跟踪我的相机和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]; 
    } 
} 

从我读过,自动释放池应该排在每次运行循环结束,所以我也不会想到,创造了一堆自动释放对象的每一帧是一个问题,他们都应该得到冲刷每一帧。我介绍了我的程序并检查了任何泄漏,但找不到任何漏洞,而且我还使用ARC,这可以最大限度地降低风险。当我分析它时,活动字节总数永远不会变化,尽管总体字节增长很快,并且没有发现泄漏。另外,didReceiveMemoryWarning从不会触发。我很难过。

回答

0

所以,我想我已经知道发生了什么。在之前的某个时候,我使用了NSZombies,然后忘了它,所以我期望被释放的所有对象实际上仍然在四处闲逛。当在乐器中进行配置时,僵尸不能算作活的,这就是为什么我不明白为什么当活动字节数没有增加时,我似乎内存不足。然而,当我升级到XCode 5时,新的内存量表显示我正在快速记忆内存,然后当我放入仪器时,Leaks被一个警告掩盖,说它自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设备上实现的瓦片基于延迟渲染策略做了自己隐藏表面移除优化 - 从不透明几何体前后排序是多余的,所以它只会浪费CPU时间。 (这里有一个体面的解释,在OpenGL ES Hardware Platform Guide for iOS。)尽管如此,您仍然应该将半透明几何图形重新排序(然后在不透明几何图形之后绘制它)以进行适当的混合。

+0

嗯,看起来你是对的,autoreleased对象不是问题。照顾你指出的那些事情,我仍然遇到一个malloc错误,只是打破了另一个地方。这一次,我做了一些GLKVector3属性的手动KVO,并且堆栈跟踪结束于didChangeValueForKey:行,具有完全相同的malloc mmap错误。既然它看起来像是一个内存问题,我已经看过乐器中的Allocations/Leaks,并且一切看起来都很好,没有泄漏,活动字节的数量永远不会增长,只是不明白从哪里开始。 – Devin