C++ Windows 返回与退出进程

C++ Windows return vs ExitProcess

本文关键字:退出 进程 返回 Windows C++      更新时间:2023-10-16

我正在尝试在没有任何CRT库的情况下在Windows上创建简单的程序。

我有两个代码:

// compile without -lkernel32
int __stdcall _main() {
return 5;
}

// compile with -lkernel32
#include <windows.h>
void __stdcall _main() {
ExitProcess(5);
}

我正在使用这个 bash 脚本使用 MinGW-w64 7.1.0 编译它们:

@echo off
del main.exe 2>nul
C:UsersMichalDownloadsmingw64bing++ main.cpp -o main.exe -O3 -s -nostdlib -lkernel32
main.exe
echo %errorlevel%
pause

输出(退出代码)相同。 (我使用的是 Windows 7 Pro 64 位)

什么代码更好?(也许更好的问题是:"返回"变体为什么有效?

编辑:

程序的入口点(默认由链接器预设)是_main(通常 CRT lib 会做一些工作,然后调用"main"函数并使用从 main 函数返回的值调用 ExitProcess(或类似的东西)。

在我的代码中,我没有使用 CRT 库,_main仍然是程序的入口点(并且不调用"main"函数)。

您是对的,为什么return版本有效是理解哪个更好的关键。

这里重要的是,main不是 Windows 控制台应用程序的入口点。 入口点在库代码中,它初始化内存,调用全局变量上的构造函数,将命令行拆分为argc/argv格式,然后调用main保存返回值。

如果main确实返回,它将返回到库代码,该代码调用atexit注册函数和静态变量析构函数,然后调用ExitProcess

因此,实际上只有一种方法可以设置退出值,即调用ExitProcess。 但是自己做会跳过库采取的清理操作——如果你调用ExitProcess那么析构函数不会被调用,你最终可能会丢失卡在写入缓冲区中的数据。

当您在没有标准库的情况下构建时,构建/销毁的库操作无关紧要,显式调用ExitProcess几乎与返回相同。 仍然有一个库提供的调用帧,它捕获您的返回值并在您不这样做时调用ExitThread,但是当没有 CRT 时,它来自操作系统本身(kernel32.dll)。 正如 RmMb 指出的那样,这是一个重要的区别,因为其他线程不会被杀死;如果所有线程都退出,则进程将退出。

如果不使用CRT,则需要直接调用ExitProcess。没有这个,您的进程根本无法终止。所以只有返回的变体是错误的。 仅当进程具有单个线程时,它才会起作用,否则进程将不会终止。


您需要了解如何终止进程。

进程将一直执行,直到发生以下事件之一:

  • 进程的任何线程都调用 ExitProcess 函数

  • 进程的最后一个线程终止

  • 任何线程调用 TerminateProcess 函数,并带有 过程

当我们使用CRT时,它在内部调用ExitProcess.当我们不使用CRT时,main是您的 exe 的真正入口点。返回后,直接返回到 kernel32 代码。kernel32 代码调用ExitThread但不ExitProcess- 这非常重要。因此,在这种情况下,仅当进程中没有其他线程时,您的进程才会终止。然而,我们永远不能假设这一点。从 Windows 10 开始,这通常是错误的。因此,在不使用CRT的情况下终止进程的唯一正确方法是直接调用ExitProcess