C++ C++;Windows返回与ExitProcess

C++ C++;Windows返回与ExitProcess,c++,winapi,C++,Winapi,我正在尝试在没有任何CRT库的Windows上创建简单的程序 我有两个密码: // compile without -lkernel32 int __stdcall _main() { return 5; } 及 输出(退出代码)相同。 (我使用的是64位Windows 7 Pro) 什么代码更好?(也许更好的问题是:“return”变体为什么起作用?) 编辑: 程序的入口点(默认由链接器预先设置)是_main(通常CRT lib做一些工作,然后调用“main”函数,并使用main函数

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

我有两个密码:

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

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

什么代码更好?(也许更好的问题是:“return”变体为什么起作用?)

编辑:

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

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

如果你没有使用CRT-你需要直接调用
ExitProcess
-没有它,你的进程根本无法终止。因此,仅返回变量-错误。 只有当进程中只有一个线程时它才会工作,否则进程不会终止


需要了解

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

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

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

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


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

,那么
返回
版本工作的原因是正确的,这是理解哪个版本更好的关键

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

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

因此,只有一种方法可以设置退出值,即调用
ExitProcess
。但是,如果您自己这样做,将跳过库执行的清理操作——如果您调用
ExitProcess
,则不会调用析构函数,最终可能会丢失卡在写缓冲区中的数据


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

使用
return
变量是可移植代码,因此应首选。@πάνταῥεῖ - 这不是可移植的变体,这是错误的变体您还需要查看exit和_exit。@πάνταῥεῖ: 许多“便携”设备依赖于CRT,当标准库被禁用时根本不工作。Raymond Chen在他的博客上回答说:
没有任何CRT库。
-所以在这种情况下,
main
才是真正的CRT入口点exe@RbMm:尽管用户入口点不是堆栈上的第一帧,内核32中仍然有一个操作系统入口点,对吗
main
是“真实”入口点,其地址列在PE头中,但执行仍然不会从那里开始。是的,不是用户模式下的第一条指令。但是kernel32入口点notcall
ExitProcess
——它调用
ExitThread
,所以返回——是错误的,不起作用。永远不会成功10@RbMm:嗯,它可以调用
ExitThread
。。。如果你想
ExitProcess
,那就错了。我不太明白Windows 10现在有什么不同?@a3f-Windows 10通常会在任何进程中自动创建工作线程,以“并行”方式加载DLL-这就是所谓的并行加载程序。因此,您的应用程序中始终有多个线程。仅仅调用
ExitThread
是不够的。但是,此工作线程在30秒空闲后退出-在这种情况下,进程可以在30秒后终止
// compile with -lkernel32
#include <windows.h>

void __stdcall _main() {
    ExitProcess(5);
}
@echo off
del main.exe 2>nul
C:\Users\Michal\Downloads\mingw64\bin\g++ main.cpp -o main.exe -O3 -s -nostdlib -lkernel32
main.exe
echo %errorlevel%
pause