7

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

“未知模块中发生了‘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 
4

2 回答 2

4

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

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

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

此外,在您继续寻找替代调试方法之前,您可能需要尝试几件事:

  1. 确保项目是在调试中构建的
  2. 检查 Visual Studio 设置以确保它在所有异常情况下都停止
  3. 如果项目设置中可用,请关闭“仅我的代码”设置(这甚至出现在 C# 项目中吗?)
  4. 打开混合模式调试/非托管调试
  5. 确保正在生成符号并将其存储在正确的位置 (*.pdb)
  6. 如果所有这些都失败了,您可以在系统事件查看器中四处寻找任何奇怪的错误
于 2013-01-07T23:51:05.383 回答
3

StackOverflowException通常是由某种无休止地调用自身的方法引起的。

它在一段时间后发生的事实让我更加坚定:你面临着无限递归。

这种行为的一个非常简单的例子是:

void SomeMethod()
{
    SomeMethod(); // StackOverflowException
}
于 2013-01-08T14:42:45.827 回答