【问题标题】:Different ways of exiting a process in C++在 C++ 中退出进程的不同方法
【发布时间】:2010-10-29 06:08:19
【问题描述】:

退出进程有多种方式:

例如:ExitProcess、ExitThread(从主线程)、退出、中止、从主线程返回、终止。

我想知道每种方法对静态/全局/自动对象销毁的影响。

例如,我有一个项目在调用 ExitProcess 时崩溃(可能是由于某些释放错误),但在调用 exit() 时却没有。 (顺便说一下,与this question 有关)。

所以基本上我想知道在什么情况下会发生上述对象的释放,以及以什么顺序(对于 VC++)。

【问题讨论】:

    标签: c++ winapi visual-c++


    【解决方案1】:

    简而言之:唯一完全安全的做法是允许main() 或您的线程函数访问return

    C++ 标准保证 (3.6.3/1, 18.3) 如果调用 exit() 将调用全局对象(包括静态对象)的析构函数,但是它明确声明 local的析构函数> 在这种情况下将调用变量。 exit() 将调用在atexit() 注册的任何函数,并且还将刷新然后关闭任何打开的stdio 流(至少包括stdinstdoutstderr)。

    调用abort() 保证不会调用本地或全局析构函数。也不会调用atexit() 注册的函数或刷新 stdio 流。

    调用诸如ExitProcess()ExitThread() 之类的任何Win32 原语肯定不会调用局部变量的析构函数,并且几乎肯定不会调用全局对象的任何析构函数,或使用atexit() 注册的任何函数。 不建议在 C++ 程序中直接调用这些函数——基本上,这些 Win32 函数和 C++ 运行时库彼此一无所知。事实上,即使是MSDN documentation for ExitThread() 也建议 C++ 程序应该从线程函数返回而不是调用 ExitThread()

    (理论上,运行时库有可能专门安排ExitProcess() 调用全局对象析构函数——这可以通过始终加载其入口点函数将执行这些调用的特定DLL 来完成,因为ExitProcess() 将使用DLL_PROCESS_DETACH 为每个加载的 DLL 调用入口点函数——但据我所知,没有实现这样做。)

    【讨论】:

    • 实际上 ExitProcess 确实会调用 atexit 注册的全局析构函数,如果它们是在 DLL 中定义的。这取决于调用 DLLMain(分离进程)的顺序。 ExitProcess 似乎首先分离 DLL,然后尝试清理自己的 atexits,而 exit() 则相反。因此,如果您声明依赖于某些外部 DLL 的静态变量,它们可能无法通过 ExitProcess 进行破坏。 (这是基于我今天所做的一些实验。)
    • 有趣的是,其他 DLL 在收到 DLL_PROCESS_DETACH 时似乎调用了它们的析构函数。 ExitProcess() 的文档没有说明 DLL 入口点的调用顺序,但即使它们以 LIFO 顺序调用,我认为如果不同 DLL 中的全局对象相互引用,问题仍然会出现。跨度>
    • 从 DLL_PROCESS_DETACH 调用 dtor 是有意义的,如果您注意到它们从 DLL_PROCESS_ATTACH 调用 ctor。但这实际上取决于创建 DLL 的编译器和调用者来安排它。查看 DLL 延迟加载以了解另一种可能的实现路径。
    【解决方案2】:

    查看ExitProcess()的源代码(发布在compuserve、usenet)

    【讨论】:

    • 想要 -1 this -- 如果可能的话,您应该避免依赖于实现细节,因为它们随时可能更改,恕不另行通知(例如,当Windows Update 后台进程接下来会安装安全更新)。也就是说,如果您确定源代码与您正在运行的版本相对应,这可能会帮助您调试一些东西。
    猜你喜欢
    • 2016-04-17
    • 1970-01-01
    • 1970-01-01
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 2013-06-25
    • 2018-09-11
    • 2020-12-29
    相关资源
    最近更新 更多