OpenGL应用程序导致d3d11.dll中的堆栈溢出



这个问题是在将Windows 10更新到1703版本后才开始发生的,该程序在1607版本上运行良好。

创建OpenGL 4.6上下文后,调用SwapBuffers()时,d3d11.dll中会触发堆栈溢出异常。以下是堆栈内容的摘要(自下而上阅读)。为什么我的纯OpenGL程序调用d3d11.dll中的函数?我甚至不知道如何调试这个,任何提示都将不胜感激。

系统规格:GeForce GT 745A,驱动程序版本388.13,Windows 10版本1703,i7 4790S,8GB ram

编辑:加载了符号,得到了一个更有用的调用堆栈:

d3d11.dll!NDXGI::CDevice::SubmitCommandCB(void *,struct _D3DDDICB_SUBMITCOMMAND const *)    Unknown
-- This block repeats several times...
nvwgf2umx.dll!00007ffdd4a226d5()    Unknown
nvwgf2umx.dll!00007ffdd4a18830()    Unknown
nvwgf2umx.dll!00007ffdd4a2363d()    Unknown
nvwgf2umx.dll!00007ffdd4d60d27()    Unknown
nvwgf2umx.dll!00007ffdd4a226d5()    Unknown
-------------------------------------------
nvwgf2umx.dll!00007ffdd4a18830()    Unknown
nvwgf2umx.dll!00007ffdd4a2363d()    Unknown
nvwgf2umx.dll!00007ffdd4d60d27()    Unknown
nvwgf2umx.dll!00007ffdd4194afb()    Unknown
nvwgf2umx.dll!00007ffdd418e57e()    Unknown
nvwgf2umx.dll!00007ffdd41b3f1d()    Unknown
nvwgf2umx.dll!00007ffdd4183518()    Unknown
nvwgf2umx.dll!00007ffdd4183750()    Unknown
d3d11.dll!NDXGI::CDevice::CreateDriverInstance(void *,void *,void *,void *,bool,bool,enum D3D_FEATURE_LEVEL,unsigned int,long (**)(struct D3D10DDI_HDEVICE,unsigned int,unsigned __int64,void *,unsigned __int64,void *))   Unknown
d3d11.dll!CDevice::CreateDriverInstance(class CContext *,void *,void *,void *,void *,unsigned int,long (**)(struct D3D10DDI_HDEVICE,unsigned int,unsigned __int64,void *,unsigned __int64,void *))  Unknown
d3d11.dll!CContext::LUCCompleteLayerConstruction(void)  Unknown
d3d11.dll!NOutermost::CDeviceChild::LUCCompleteLayerConstruction(void)  Unknown
d3d11.dll!NOutermost::CDevice::CreateLayeredChild(unsigned int,void const *,unsigned __int64,struct ID3D11LayeredUseCounted *,struct _GUID const &,void * *)    Unknown
d3d11.dll!CDevice::LLOCompleteLayerConstruction(void)   Unknown
d3d11.dll!NDXGI::CDevice::LLOCompleteLayerConstruction(void)    Unknown
d3d11.dll!NOutermost::CDevice::FinalConstruct(struct NOutermost::CDevice::TConstructorArgs const &) Unknown
d3d11.dll!TComObject<class NOutermost::CDevice>::TComObject<class NOutermost::CDevice>(void *,struct NOutermost::CDevice::TConstructorArgs const &,struct _GUID const &,void * *)   Unknown
d3d11.dll!TComObject<class NOutermost::CDevice>::CreateInstance(struct NOutermost::CDevice::TConstructorArgs const &,void *,void *,struct _GUID const &,void * *)   Unknown
d3d11.dll!D3D11CreateLayeredDevice(unsigned int,void const *,unsigned __int64,struct ID3D11LayeredDevice *,struct _GUID const &,void * *)   Unknown
d3d11.dll!D3D11CoreCreateLayeredDevice()    Unknown
d3d11.dll!D3D11RegisterLayersAndCreateDevice(struct D3D11_EXTENSIONS const &,class NDXGI::CUMDAdapter *,enum D3D_FEATURE_LEVEL,enum D3D_FEATURE_LEVEL,unsigned __int64,unsigned int,struct ID3D11Device * *)    Unknown
d3d11.dll!D3D11CoreCreateDevice()   Unknown
d3d11.dll!D3D11CreateDeviceAndSwapChainImpl(struct IDXGIAdapter *,enum D3D_DRIVER_TYPE,struct HINSTANCE__ *,unsigned int,enum D3D_FEATURE_LEVEL const *,unsigned int,unsigned int,struct DXGI_SWAP_CHAIN_DESC const *,struct IDXGISwapChain * *,struct ID3D11Device * *,enum D3D_FEATURE_LEVEL *,struct ID3D11DeviceContext * *)    Unknown
d3d11.dll!D3D11CreateDeviceAndSwapChain()   Unknown
d3d11.dll!D3D11CreateDeviceImpl(struct IDXGIAdapter *,enum D3D_DRIVER_TYPE,struct HINSTANCE__ *,unsigned int,enum D3D_FEATURE_LEVEL const *,unsigned int,unsigned int,struct ID3D11Device * *,enum D3D_FEATURE_LEVEL *,struct ID3D11DeviceContext * *)  Unknown
d3d11.dll!D3D11CreateDevice()   Unknown
nvoglv64.dll!0000000058f193a9() Unknown
nvoglv64.dll!0000000058f18438() Unknown
nvoglv64.dll!0000000058f40b8e() Unknown
nvoglv64.dll!0000000058f3fcd3() Unknown
nvoglv64.dll!0000000058f22607() Unknown
nvoglv64.dll!0000000058f41a42() Unknown
nvoglv64.dll!00000000590291fd() Unknown
nvoglv64.dll!000000005903437d() Unknown
nvoglv64.dll!00000000590452e7() Unknown
nvoglv64.dll!0000000058ee8ffe() Unknown
nvoglv64.dll!00000000590095e2() Unknown
nvoglv64.dll!0000000058febb4d() Unknown
nvoglv64.dll!0000000058febc60() Unknown
nvoglv64.dll!0000000058ef9e66() Unknown
nvoglv64.dll!0000000058ef9fd5() Unknown
nvoglv64.dll!0000000058ef9dc4() Unknown
nvoglv64.dll!0000000058ef98c6() Unknown
nvoglv64.dll!0000000058ee355a() Unknown
opengl32.dll!wglSwapBuffers()   Unknown
gdi32full.dll!SwapBuffers() Unknown

在彻底检查代码和相关输入数据之前,我们只能推测可能的原因。

查看调用链中的重复块,您可能已经在驱动程序中的某个位置使用了无限递归。这可能是由于传递给OpenGL API调用的参数错误,或者由于OpenGL实现中的错误。在指责英伟达或微软之前,你应该彻底检查一下你的程序。为了调试此错误,您可以尝试以下操作:

  • 在做任何其他事情之前,先实现正确的OpenGL错误检查。确保从所有OpenGL调用中检索返回代码,检查它们是否失败,打印调试消息并触发断点,或者在这些调用中的任何一个失败时终止程序(例如,请参见此处)。在调试模式下实现调试回调扩展,如这里所示
  • 在传统的C++调试器下运行程序,就像在Visual Studio中一样。检查堆栈和堆是否可能损坏。启用更多编译器警告,如果发现任何可疑情况,请尝试各种静态代码检查器和运行时分析器
  • 在图形调试器(如Nvidia Nsight)下运行程序,并在API调用、管道的各个阶段和着色器中查找可能的错误
  • 查找并隔离导致错误的OpenGL函数调用。逐渐删除或注释掉看起来最可疑的代码片段(例如,接近崩溃的代码、使用堆内存的代码等)。查看错误是否消失。如果是这样,那么您可能已经删除了导致错误的代码。把它拿回来,看看是否再次出现错误。从大块代码开始,逐渐减少删除的代码量,使搜索更加精确。最终目标是提出一个重现错误的最小代码示例
  • 当你找到它时,在StackOverflow上发布这个最小的代码(例如,添加到你的问题中作为更新),这样社区就可以查看它
  • 如果您的最小示例中没有错误,但它崩溃了,请向Nvidia提交错误报告,包括最小示例代码。同时,您也可以尝试不同的驱动程序版本,看看它们是否受到影响
  • 您也可以尝试在英特尔或AMD显卡上运行该代码。例如,您的CPU中集成了Intel图形。如果在另一个GPU上也可以观察到这个问题,那么很可能不是英伟达的错(两个不同的供应商不太可能在同一个地方犯同样的错误)
  • 如果您的代码可以跨操作系统移植,或者至少如果最小的例子是,请尝试在另一个操作系统上构建并运行它。Linux有很好的工具来调试C++代码。有时,简单地更改编译器就会发现很多明显的错误。此外,您还将拥有valgrind、clang消毒器和OpenGL堆栈的不同实现,包括图形驱动程序(例如,Nvidia驱动程序有两种不同的实现,一种是Nvidia的专有驱动程序,另一种是开源的Nouveau驱动程序)。Linux上还有与OpenGL相关的调试工具
  • 请注意,当分析代码试图隔离错误调用时,您可能找不到一个,因为在某些情况下,有几个调用是导致问题的必要条件。这些调用可以彼此相邻,也可以分布在多个渲染帧上。当使用多线程和/或多个上下文时,事情变得特别困难。在这些情况下,尽量减少代码量、删除线程和上下文应该会有所帮助
  • 请注意,错误没有出现在您以前的配置(例如不同的Windows版本)或其他供应商的OpenGL实现中,这并不一定意味着没有错误。它可能被不同的实现隐藏或忽略。在满足特定条件之前,某些错误可能不会显现。您尝试的配置(操作系统、编译器、OpenGL实现、驱动程序)越多,暴露的错误就越多。希望上面的提示能帮助你找到这些错误和条件

调试愉快!

最新更新