VS2017下C++ AMP退出码异常:如何清理AMP获取正确退出码?
针对你遇到的VS2017 + Win10 1709环境下,C++ AMP使用后进程退出码异常的问题,我结合你排查到的SchedulerBase代码问题,整理了几个有效的清理步骤,能让父进程通过::GetExitCodeProcess拿到预期的0退出码:
核心原因
VS2017中C++ AMP的MFC调度器实现(SchedulerBase.cpp)在调用RegisterWaitForSingleObject时,可能因Win10 1709的API行为差异触发内部异常。虽然异常被内部捕获,但注册的等待对象未被正确注销,进程退出时系统检测到未清理的同步资源,从而返回非0的无效退出码;而VS2013的调度器实现没有这个遗留问题。
具体清理步骤
你需要在进程退出前(比如main函数末尾、MFC应用的ExitInstance方法中)主动执行以下清理操作:
等待所有GPU任务完成
确保所有C++ AMP异步任务都执行完毕,避免残留未完成的命令队列:concurrency::wait_for_all();显式刷新并释放accelerator_view
强制提交所有待执行的GPU命令,然后重置accelerator_view对象触发析构清理:// 如果你持有自定义的accelerator_view对象 acc_view.flush(); acc_view = concurrency::accelerator_view(); // 重置触发析构 // 如果使用的是默认视图,显式获取后重置 auto default_acc_view = concurrency::accelerator().default_view; default_acc_view.flush();清理C++ AMP调度器资源
主动释放调度器持有的系统资源,包括注销可能残留的等待对象:if (concurrency::current_scheduler::exists()) { concurrency::current_scheduler::release(); } // 针对部分版本的C++ AMP,还可以尝试调用全局清理函数 concurrency::scheduler::cleanup();确保所有AMP相关对象提前析构
在进程退出前,确保所有accelerator、accelerator_view、array等C++ AMP对象都已超出作用域或被显式销毁,避免编译器优化跳过析构逻辑。
验证效果
执行以上步骤后,进程退出时会正确清理所有C++ AMP相关的同步资源和调度器对象,父进程调用::GetExitCodeProcess就能拿到预期的0退出码了。
内容的提问来源于stack exchange,提问作者Paulo Eduardo Pilon

