是否需要通过ExitProces()或TerminateProcess()终止Windows进程?

问题描述 投票:0回答:3

我有这个简单的程序:

#include <windows.h>
int WINAPI startMeUp() {
  return 0;
}

我使用Visual Studio的命令行工具编译,如下所示:

cl /nologo /GS- /Gs- /c /W4 main.c /Fomain.obj
link /nologo main.obj /subsystem:console /entry:startMeUp /nodefaultlib kernel32.lib user32.lib /OUT:the.exe

当我然后执行.\the.exe时,会显示一个消息框,指出the.exe已停止工作 - 一个问题导致程序停止正常工作。 Windows将关闭程序并在解决方案可用时通知您

return 0;替换ExitProcess(0);并重新编译/链接后,.\the.exe运行得很好。

所以,在我看来,需要ExitProcess()来正确结束一个过程。

因为我很确定我已经通过返回退出值从入口点函数返回了工作程序,所以我不确定可移植可执行文件是否需要ExitProcess()终止进程。

编辑有趣的是,如果我在MessageBox(NULL, "world", "hello", 0);之前放置一个return 0;(因此没有ExitProcess()调用),可执行文件也运行正常。

编辑II当我添加链接器选项/export:startMeUp时,链接器用LNK4216警告我,但我可以执行创建没有问题。

当我在创建的两个exes上使用dumpbin /all时,我看到错误的可执行文件有

 0 [       0] RVA [size] of Export Directory

而新的,有工作的

2000 [      40] RVA [size] of Export Directory

此外,工作可执行文件由两部分组成:.text.rdata,而有缺陷的部分只有.text部分。可执行代码似乎包含在.rdata部分中,因此它在错误的部分中缺失。

至于为什么,我不知道。

windows winapi portable-executable entry-point
3个回答
0
投票

windows进程退出或进程退出时或TerminateProcess调用时的最后一个线程。因为你的过程中可能有额外的(隐式创建的)线程 - 你需要直接或间接调用TerminateProcess(或ZwTerminateProcess)。

ExitProcess内部调用TerminateProcess(确实是ZwTerminateProcess),但在此之前做了一些工作,正确的进程关闭。包括使用DLL_PROCESS_DETACH通知调用所有DLL入口点

所以一般来说你必须调用ExitProcess(更正确)或TerminateProcess

如果您自己编写入口点,则必须使用正确的签名

int WINAPI startMeUp(void*)

这是stdcall函数,它占用1个参数(指向PEB的指针)。当你从这个api返回到系统时 - 只调用RtlExitUserThread,这导致线程退出或所有进程退出,如果这是进程中的最后一个线程。从startMeUp返回后,甚至在x86系统堆栈指针上设置不正确这不会导致错误,因为只是RtlExitUserThread并且它永远不会返回。很难说在没有查看二进制文件的情况下导致测试崩溃的原因,但更快需要在具体系统上查看(调试)。但这是不寻常的 - 这绝不是。你的进程必须或者只是退出或者仍然存在(无限或一些时间)后台存在的其他线程


0
投票

如果你只是问exec中是否需要ExitProcess()我可以严格回答yoo:NO

我写了一个编译器,它生成exe和最小程序(如果不是说exe标题)可能只有一个字节:0xC3即ret - 这样的程序运行时立即返回但是正确


-2
投票

是的,ExitProcess是必需的,否则你最终会抛出异常,因为无处可去,你无法停止处理器。

但是,该条目通常不是用户提供的,它由CRT(WinMainCRTStartup)提供,它在调用WinMain()函数之前也初始化全局变量。

因此,您需要做的就是提供WinMain。

编辑后编辑:ExitProcess可能由MessageBox调用后创建的一些异常处理程序调用。你不(也不能)知道。

© www.soinside.com 2019 - 2024. All rights reserved.