我注意到许多使用直接Win32调用构建的汇编语言示例(没有C运行时依赖性)说明了使用对ExitProcess()的显式调用来在入口点代码的末尾结束程序。我不是在谈论使用ExitProcess()在程序中的某个嵌套位置退出。令人惊讶的是,入口点代码只是通过RET指令退出的示例较少。想到的一个例子是着名的TinyPE,其中程序变量以RET指令退出,因为RET指令是单个字节。使用ExitProcess()或RET似乎都可以完成这项工作。
来自可执行文件入口点的RET将EAX的值返回给KERNEL32中的Windows加载程序,最终将退出代码传播回NtTerminateProcess(),至少在Windows 7上。在Windows XP上,我想我记得看到ExitProcess()甚至直接在线程清理链的末尾调用。
由于汇编语言中有很多值得尊重的优化,纯粹是在生成较小的代码时选择的,我想知道为什么更多的代码浮动更喜欢显式调用ExitProcess()而不是RET。这是习惯还是有其他原因?
从最纯粹的意义上讲,RET指令不会优于直接调用ExitProcess()吗?直接调用ExitProcess()似乎类似于通过从任务管理器中删除它来退出程序,因为这会使返回到Windows加载程序称为入口点的正常流程短路,从而跳过各种线程清理操作? / p>
我似乎找不到任何特定于此问题的信息,所以我希望有人可以对这个主题有所了解。
答案 0 :(得分:11)
如果从C运行时库调用主函数,则退出将导致调用ExitProcess()并且进程将退出。
如果您的主要功能是由Windows直接调用的,那么汇编代码就是这种情况,那么退出只会导致线程退出。当且仅当没有其他线程时,该进程将退出。这是现在的问题,因为即使你没有创建任何线程,Windows也可能代表你创建了一个或多个。
据我所知,这种行为没有正确记录,但在Raymond Chen的博客文章"If you return from the main thread, does the process exit?"中有描述。
(我也在Windows 7和Windows 10上对此进行了测试,并确认他们的行为与Raymond描述的相同。)
附录:在最新版本的Windows 10中,进程加载器本身是多线程的,因此当进程首次启动时,总是是其他线程。< / p>