当我甚至无法步入代码时,如何调试“此应用程序已请求运行时以不寻常的方式终止。”?

4
我有一个C++程序,在进程开始运行时就出现了这个错误,似乎是在任何用户代码执行之前就出现了。只有启用内联时才会发生。即使内置调试符号,我也无法进入代码。当我按下Visual Studio中的F10时,我立即收到错误并停止了程序。我检查了“调试/异常”中的所有异常/检查,但仍然没有断点。
通常我会认为这样的情况是由于缺少运行时依赖关系引起的,但我非常确定这不是这种情况(使用Dependency Walker进行验证)。
编辑:我使用了Steve Townsend的建议,使用CDB,现在我能够逐步执行程序的预用户代码部分。最终的堆栈跟踪如下:
Child-SP          RetAddr           Call Site
00000000`0008e308 00000000`7541601a ntdll!ZwTerminateProcess+0xa
00000000`0008e310 00000000`7540cf87 wow64!Wow64EmulateAtlThunk+0x86ba
00000000`0008e340 00000000`7539276d wow64!Wow64SystemServiceEx+0xd7
00000000`0008ec00 00000000`7540d07e wow64cpu!TurboDispatchJumpAddressEnd+0x24
00000000`0008ecc0 00000000`7540c549 wow64!Wow64SystemServiceEx+0x1ce
00000000`0008ed10 00000000`7776ae27 wow64!Wow64LdrpInitialize+0x429
00000000`0008f260 00000000`777672f8 ntdll!LdrGetKnownDllSectionHandle+0x1a7
00000000`0008f760 00000000`77752ace ntdll!RtlInitCodePageTable+0xe8
00000000`0008f7d0 00000000`00000000 ntdll!LdrInitializeThunk+0xe

1
有使用任何外部(非Windows)库吗? 我曾经遇到过这个问题,是由我的一个外部库(来自LabView)引起的。我不得不延迟加载它。 - RedX
即使已经构建了调试符号,我也无法步入代码。你是指在 main() 执行之前吗?这只是一个猜测...全局变量是在主执行开始之前创建的,因此可能存在问题。 - Alok Save
@Mark Ingram:不行。 @AJG85:显然不行! @RedX:我有一堆自己的库,但是那些被其他正常工作的可执行文件使用,这让我相信问题出在应用程序代码中(只有一个文件;它是一个命令行应用程序)。 @AIs:有没有办法深入了解这些? - Matt Chambers
2
@Matt Chambers:只需在创建全局对象的类的构造函数中设置断点即可。 - Alok Save
我已经缩小了范围,发现是我的一些代码导致了.NET依赖关系。但是另一个具有相同依赖项的应用程序可以正常工作。 :/ 我将尝试使用启用内联的调试构建。 - Matt Chambers
显示剩余5条评论
2个回答

2
你可以尝试设置 Process Dumper 并为你的EXE配置它,在任何进程退出时创建一个转储文件。然后从命令行启动进程,以排除IDE的任何痕迹。
这应该会为您提供后期调试的转储文件,并可能提供有用的退出线程调用堆栈。

啊,我想你把我带到了正确的兔子洞。看起来UserDump(用户模式进程转储程序)仅适用于Windows 2003及更早版本。对于Vista和7(我在Windows 7 64位上),谷歌建议使用adplus。但后来我读到了这个: 在以下情况下不应使用ADPlus:如果您需要排除在启动过程中意外结束的应用程序或进程。您只能将ADPlus与成功启动进程一起使用。如果您需要解决在启动过程中意外终止的进程问题,应改用CDB、WinDbg或UserDump。 - Matt Chambers
希望这可以帮到你。我最初想建议使用WinDbg,但不确定它是否可以在IDE之前钩住进程。CDB可能是最好的选择,缺乏GUI不会成为一个大问题,因为这个问题很容易复现且比较简单。 - Steve Townsend
现在至少我能看到崩溃之前的一些步骤了!但是我不知道它意味着什么。:( 请查看更新后的问题。 - Matt Chambers
我将这个设为“答案”,尽管我并没有真正接近使用这种方法来解决我的问题。 :( 我最终重构了一些代码以删除库依赖项(其中一个是我自己的库,它与套件中的其他可执行文件一起正常工作),然后问题停止发生。我可能以后还会遇到它... - Matt Chambers
@Matt - 不确定你是否会再次遇到这个问题。如@Adrian的答案所述,这可能与全局变量的初始化顺序有关,因此重新排列或删除依赖项可能会解决此问题。无论如何,很高兴你又可以继续工作了。 - Steve Townsend

1

这可能与全局变量初始化的顺序有关。在C++中,模块之间的顺序是未指定的。因此,如果全局变量的初始化器依赖于另一个模块中已经初始化的全局变量,则会出现问题。

可以在调用main(或wmain、WinMain或您使用的任何其他函数)之前运行的CRT初始化代码中设置断点。您可以步进该代码并查看导致问题的原因。

另一个可能的原因是DllMain函数在DLL_PROCESS_ATTACH期间返回错误或抛出异常。


我的全局变量都是基本类型或没有任何依赖关系。我非常清楚静态初始化顺序问题。对于具有依赖关系的全局变量,我使用boost.vault单例类。但是它是按需实例化的,而不是在main函数之前。而且这个崩溃的特定应用程序根本没有添加任何全局变量(无论是单例还是其他),那么为什么它会崩溃,而使用相同库的其它应用程序却不会呢? - Matt Chambers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接