2013-09-05 37 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