结束进程
进程可以以4种方式结束:
- 主线程入口点函数(_tmain/_tWinMain)返回时结束,建议所有进程都以这种方式结束
- 进程中的某线程调用了ExitThread函数,应当避免这种情况
- 另一进程中的某线程调用了TerminateProcess函数,应当避免这种情况
- 进程中的所有线程中止,这种情况比较罕见
下面我们来分别讨论这4种情形。
主线程入口点函数返回
在设计应用程序时,你应该保证其进程只有在主线程入口点函数返回时才终止,这也是确保能够正确释放主线程使用的所有资源的唯一途径。主线程入口点函数正常返回时,系统将会执行下面的动作:
- 主线程创建的所有C++对象将被正确的销毁
- 主线程堆栈占用的内存空间将被释放
- 系统会把入口点函数的返回值作为进程的退出码写入进程内核对象中
- 进程/主线程内核对象引用计数减1
调用ExitProcess函数
当进程中的任意线程调用ExitProcess函数时,进程将被终止。我们在前面的章节提过,C/C++运行时启动函数在主线程入口点函数(WinMain、wWinMain、main或wmain)返回时,会清理进程使用的所有C运行时资源,然后显式调用ExitProcess,并将入口点函数的返回值传给ExitProcess。这也解释了主线程入口点函数返回会导致进程中止的原因,注意此时进程中的所有线程也会随进程一起终止。
根据Windows PlatformSDK文档的说法,当进程中仍然有线程在执行时,进程不会终止。对于操作系统而言这是正确的,可是C/C++运行时的实现却并非如此:当主线程入口点函数返回时,无法有进程中是否有其它正在执行的线程,进程都会被ExitProcess函数终止。然而如果你在入口点函数中调用了ExitThread而不是将其返回或调用ExitProcess,主线程会停止执行,但进程会一直存在直到其中最后一个线程中止。
调用ExitThread和ExitProcess会导致线程或进程在函数内立刻终止,对于操作系统来说这无关紧要,因为系统会保证释放线程/进程用到的系统资源,但是,C/C++程序应该避免调用这些函数,C/C++运行时可能无法及时执行清理工作,比如下面的代码: