我目前正在使用 GLKit 进行一些 OpenGL 绘图。我创建了一个普通的 UIViewController,然后在容器中添加了一个 GLKViewController 子类来进行我的绘图。虽然最初一切都运行良好,但如果我让我的程序运行一段时间(可能是 15-30 分钟),最终它会崩溃并给我以下错误。
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 永远不会触发。我难住了。