exit无法设置错误代码 我有一个C++的Windows程序,它无法设置退出代码。这个程序非常复杂,我目前无法用一个简单的测试用例重现它。我确实知道程序调用exit(1),因为我在那一行上有一个断点。在我跨过它之后,调试器(VS2010)立即打印程序program.exe已退出,代码为0(0x0)。当我从shell运行它时,%ERRORLEVEL%也设置为0

exit无法设置错误代码 我有一个C++的Windows程序,它无法设置退出代码。这个程序非常复杂,我目前无法用一个简单的测试用例重现它。我确实知道程序调用exit(1),因为我在那一行上有一个断点。在我跨过它之后,调试器(VS2010)立即打印程序program.exe已退出,代码为0(0x0)。当我从shell运行它时,%ERRORLEVEL%也设置为0,c++,windows,windows-server-2008,exit-code,C++,Windows,Windows Server 2008,Exit Code,我使用子系统:控制台和普通的旧main(没有WinMain) 这只发生在Windows Server 2008 R2上,而不是我的Windows 8.1笔记本电脑上。我在两者上运行相同的可执行文件 我曾尝试使用exit、\u exit、ExitProcess和return(有问题的调用在main中),但这些似乎都没有任何效果。我还尝试返回其他代码,也没有结果 有一个例子,但我无法重现其中描述的结果。我的程序确实使用线程 如何处理调试此问题?我相当困惑 我已尝试使用exit、\u exit、Exi

我使用
子系统:控制台
和普通的旧
main
(没有WinMain)

这只发生在Windows Server 2008 R2上,而不是我的Windows 8.1笔记本电脑上。我在两者上运行相同的可执行文件

我曾尝试使用
exit
\u exit
ExitProcess
return
(有问题的调用在
main
中),但这些似乎都没有任何效果。我还尝试返回其他代码,也没有结果

有一个例子,但我无法重现其中描述的结果。我的程序确实使用线程

如何处理调试此问题?我相当困惑

我已尝试使用exit、\u exit、ExitProcess和return

您已经排除了所有合理的解释,尤其是ExitProcess()。只剩下一种可能性,您需要尝试TerminateProcess()。如果这仍然不能设置退出代码,那么你需要把那台机器从四层楼的窗户里推出来

但我们期望它现在能起作用。ExitProcess()和TerminateProcess()之间的区别在于前者确保所有DLL都由终止通知。它们的DllMain()函数使用fdreason=DLL\u PROCESS\u DETACH调用。这使DLL有机会做一些令人讨厌的事情,比如调用Exit/TerminateProcess()本身,从而破坏了退出代码

如果没有所有的源代码,查找这样的DLL可能会很困难。也可能是注射式的,现在已经有太多了。最好的做法是在系统调用上设置一个断点,这样您就可以在act中捕获它,您可能无论如何都想这样做


进入main()后,使用Debug>newbreakpoint>breakat函数并输入
{,ntdll.dll}_NtTerminateProcess@8
。按F5键,调试器现在在程序终止之前停止。查看调用堆栈以找到作恶者。

多线程程序中涉及exit()、_exit()、ExitProcess()和其他程序的奇怪症状-特别是如果症状在主机之间不同-有一种由不同线程修改或访问的变量的气味,而没有同步

查看链接到的另一个线程,您似乎正在使用一个可变变量在线程之间进行通信,但没有使用任何形式的同步(例如,访问该变量值的代码和修改该值的代码需要通过临界段、互斥体或类似构造进行协作)

这一点点间接证据使气味更加强烈

我怀疑的基本问题是,将变量声明为volatile既不必要也不足以确保变量始终具有对程序有意义的值。特别是,当修改仅部分完成时,阻止正在修改变量的线程被抢占,以及阻止另一个线程尝试访问或修改受影响的变量是不够的

如果你查阅Herb Sutter的一些文章(特别是他“本周大师”系列中有关线程同步的文章),你会发现关于为什么会这样的详细解释。其他作者也描述了这样的事情,但萨特的文章是我能马上回忆起来的

解决方案是引入一些同步方法,让程序中的每个线程在访问或修改它们之间共享的变量之前都认真地使用它。这避免了各种问题(竞争条件、中途抢占的操作),这些问题会导致您描述的症状

这样的问题很少通过使用调试器来解决。原因是这些症状是一种突发性的特征。在不同的执行线程中,一些不太可能且通常是独立的事件必须同时发生。调试器通常会更改程序中事件的计时,计时是出现症状时的关键考虑因素

选项包括使关键变量原子化(因此特定操作不能被抢占)、关键部分(线程在程序中显式协作)或互斥体(根据定义,互斥体允许不同程序中的线程在访问共享内存之前显式协作)

是的,这在您的程序中引入了一个瓶颈,即每个线程都必须会合并可能互相等待。这可能会影响程序的吞吐量。有些人主张使用易变变量来避免这种担忧。通常情况下,结果是长时间运行的程序出现间歇性症状,如您在本问题和您链接的“类似问题”中所述

无论您使用的是标准的同步方式(例如,在C++11中引入的)还是windows特定的同步方式(WIN API函数),都无关紧要。重要的是,您使用了一种有意的同步方法,而不仅仅是使变量易变。不同的同步选项有不同的权衡,所以您需要根据您的计划的需要做出相应的决定

另一个需要考虑的问题是向所有线程发送信号,以便它们干净地关闭,等待它们全部关闭,捕获它们的退出代码,然后退出程序。在运行main()的线程中执行此操作通常不太容易出错,而main()最终会启动进程,因此更有可能访问其中的信息