简单Windows DirectX应用程序点击关闭后未正常终止,调试出现LNK1168错误的问题排查
我来帮你分析一下这个问题,你遇到的两个现象其实是相关的,根源出在代码里的资源管理和消息循环逻辑上:
问题根源分析
1. 进程无法正常终止的原因
- Direct3D COM资源未释放:你创建了
pD3D、pDev、pVB这些COM对象,但在程序退出前完全没有调用Release()方法释放它们。COM对象依赖引用计数管理生命周期,只要有对象的引用计数不为0,进程就不会正常退出,导致后台持续运行并打印update日志。 - 消息循环逻辑瑕疵:当前的消息循环在处理完所有消息后才检查
WM_QUIT信号,即便收到了退出消息,仍可能继续执行一轮游戏逻辑;而且窗口关闭后,Present操作已经失效,但代码没有处理这种失败场景,会导致无效的渲染循环持续运行。
2. LNK1168编译错误的原因
因为前一次的进程没有正常终止,仍然占用了生成的Game_Loop_Windows_1.exe文件,导致链接器无法写入新的可执行文件,所以会抛出无法打开文件的错误。
解决方案
1. 释放Direct3D资源
在退出消息循环后,添加COM资源释放代码,这是COM编程的基本规范:
// 在消息循环结束后、程序退出前释放所有Direct3D资源 if (pVB) pVB->Release(); if (pDev) pDev->Release(); if (pD3D) pD3D->Release();
把这段代码放在OutputDebugString(_T("--> AFTER MSG LOOP END <--\n"));之前,确保所有创建的COM对象都被正确释放。
2. 修正消息循环逻辑
调整消息循环结构,确保收到WM_QUIT后立即退出,同时处理Present失败的场景:
while (TRUE) { // 优先处理系统消息 if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) { // 收到退出消息直接终止循环 if (Msg.message == WM_QUIT) { break; } TranslateMessage(&Msg); DispatchMessage(&Msg); } else { // 仅当无系统消息时执行游戏逻辑 auto current_time = clock::now(); auto frame_time = current_time - start_time; start_time = current_time; lag += duration_cast<nanoseconds>(frame_time); while (lag >= timestep) { lag -= timestep; // 检查设备是否还可用,避免窗口关闭后无效渲染 HRESULT hr = pDev->Clear(0, 0, D3DCLEAR_TARGET, 0xff000000, 1, 0); if (FAILED(hr)) { PostQuitMessage(0); break; } pDev->BeginScene(); pDev->SetFVF(OURVERT_FVF); pDev->SetStreamSource(0, pVB, 0, sizeof(OurVertex)); pDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); pDev->EndScene(); hr = pDev->Present(0, 0, 0, 0); if (FAILED(hr)) { // Present失败说明窗口已失效,主动触发退出 PostQuitMessage(0); break; } update(lag.count()); } } }
这样修改后,程序会更及时响应退出信号,且窗口关闭后会主动终止游戏循环。
3. 临时应急处理
如果下次再遇到进程未终止的情况,可以打开任务管理器,找到Game_Loop_Windows_1.exe进程并强制结束,就能正常重新编译了。
内容的提问来源于stack exchange,提问作者Daros911
相关产品推荐
相关产品推荐

