C++ C++;Windows返回与ExitProcess
我正在尝试在没有任何CRT库的Windows上创建简单的程序 我有两个密码: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函数
// 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入口点notcallExitProcess
——它调用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