如何在没有源代码链接的情况下调试System.StackOverflowException?

are*_*mes 7 c# xna

最近,我经常遇到类型错误

"未知模块中发生了'System.StackOverflowException'类型的未处理异常."

这发生在一个游戏(我开发)中,具有相当大的代码库(C#/ XNA).但通常只有在玩游戏几分钟后才会出现错误(而不是每次运行).

问题是,不幸的是,Visual Studio调试器似乎无法进一步本地化问题,只是让我检查汇编代码而不参考我的源代码行.怎么可以调试这样的错误?我想像Valgrind这样的工具在C#中不可用.是否有更好的调试器可以显示问题在源代码中的本地化位置?

应用下面建议答案中的步骤时,调用堆栈可用.它是:

ntdll.dll!_NtWaitForSingleObject@12()  + 0x15 bytes 
ntdll.dll!_NtWaitForSingleObject@12()  + 0x15 bytes 
KernelBase.dll!_WaitForSingleObjectEx@12()  + 0xcb bytes    
kernel32.dll!_WaitForSingleObjectExImplementation@12()  + 0x43 bytes    
clr.dll!CLREvent::CreateManualEvent()  - 0x15f3bb bytes 
clr.dll!CLREvent::CreateManualEvent()  - 0x15f37a bytes 
clr.dll!CLREvent::WaitEx()  + 0x47 bytes    
clr.dll!CLREvent::Wait()  + 0x19 bytes  
clr.dll!Thread::WaitSuspendEventsHelper()  + 0xa8 bytes 
clr.dll!Thread::WaitSuspendEvents()  + 0x17 bytes   
clr.dll!Thread::RareEnablePreemptiveGC()  + 0x181977 bytes  
clr.dll!Thread::RareDisablePreemptiveGC()  + 0x38e3 bytes   
clr.dll!Debugger::SendException()  + 0x12b bytes    
clr.dll!Debugger::LastChanceManagedException()  + 0x19f bytes   
clr.dll!NotifyDebuggerLastChance()  + 0x79 bytes    
clr.dll!WatsonLastChance()  + 0x166 bytes   
clr.dll!EEPolicy::HandleFatalStackOverflow()  + 0x189 bytes 
clr.dll!EEPolicy::HandleStackOverflow()  + 0xd8 bytes   
clr.dll!_COMPlusFrameHandler()  + 0xff302 bytes 
ntdll.dll!ExecuteHandler2@20()  + 0x26 bytes    
ntdll.dll!ExecuteHandler@20()  + 0x24 bytes 
ntdll.dll!_RtlDispatchException@8()  + 0xd3 bytes   
ntdll.dll!_KiUserExceptionDispatcher@8()  + 0xf bytes   
clr.dll!SystemNative::ArrayCopy()  + 0x19 bytes 
mscorlib.ni.dll!6ed326a2()  
Frames below may be incorrect and/or missing, no symbols loaded for mscorlib.ni.dll 
Run Code Online (Sandbox Code Playgroud)

Ray*_*Ray 4

如果崩溃发生在 ntdll.dll 上,您需要它的符号,但我认为更可能的是您传递了一些奇怪的垃圾,导致它崩溃。您是否进行了可能会导致崩溃的 Windows API 调用?

另一位用户在这里提到的另一种可能性是,您可能在耗尽堆栈的某个地方进行递归调用。如果调用非托管代码片段,这将尤其成问题:

  • 是否存在可能导致无限循环的逻辑条件?
  • 是否有任何构造函数会无意中进行递归调用?
  • 您的代码中是否有任何可能被卡住的递归方法?

另外,在寻找替代调试方法之前,您可能需要尝试以下几件事:

  1. 确保项目是在 debug 中构建的
  2. 检查 Visual Studio 设置以确保它在出现所有异常时停止
  3. 如果项目设置中可用,请关闭“仅我的代码”设置(这是否会出现在 C# 项目中?)
  4. 打开混合模式调试/非托管调试
  5. 确保符号正在生成并存储在正确的位置 (*.pdb)
  6. 如果所有这些都失败,您可以在系统事件查看器中浏览并查找任何奇怪的错误