在 Mac 下点击窗口的关闭按钮产生 EXC_BAD_ACCESS

我发现 cocos2dx 4.0 版本在 Mac 系统(版本:13.0.1)下的一个 BUG
当点击窗口左上方的关闭系统的按钮来关闭程序时,会产生一个 EXC_BAD_ACCESS
发生的位置在 cocos2d/cocos/renderer/backend/metal/CommandBufferMTL.mm 文件的 368 行,修改方式需要将下面这段代码

[_mtlCommandBuffer addCompletedHandler:^(id<MTLCommandBuffer> commandBuffer) {
    // GPU work is complete
    // Signal the semaphore to start the CPU work
    dispatch_semaphore_signal(_frameBoundarySemaphore);
}];

修改为

[_mtlCommandBuffer addCompletedHandler:^(id<MTLCommandBuffer> commandBuffer) {
        // GPU work is complete
        // Signal the semaphore to start the CPU work
        if (_frameBoundarySemaphore != nil) {
            dispatch_semaphore_signal(_frameBoundarySemaphore);
        }
    }];

刚好我也遇到过,我对mac os并不熟悉,我的解决方法可能有误,仅供参考。

这里的代码应该是GPU渲染完成后的回调,如果在dispatch_semaphore_signal(_frameBoundarySemaphore);设置断点会发现,这里的代码并不在主线程(ui线程)中执行的,也就意味着当程序退出时,拥有_frameBoundarySemaphore这个信号量的对象已经被销毁,这个时候如果再回调这里访问这个信号量就会出错。

我是在Application::run()里面退出渲染循环之后,在销毁资源之前加一个延时等待gpu渲染完成回调。
像这样:

while (!glview->windowShouldClose())
{
    lastTime = getCurrentMillSecond();
    
    director->mainLoop();
    glview->pollEvents();

    curTime = getCurrentMillSecond();
    if (curTime - lastTime < _animationInterval)
    {
        usleep(static_cast<useconds_t>((_animationInterval - curTime + lastTime)*1000));
    }
}

//add code...
[NSThread sleepForTimeInterval:0.01];

如果有误,还请指正。

我也是初学者,大家一起学习,哈哈

当然最好的做法应该是去等待这个信号量,不过我对底层的代码了解还比较有限,我暂时先延时了