使用ExitProcess退出时为什么还会报运行时错误

通常情况下会以为ExitProcess就是直接结束并退出进程,其实不然,根据MSDN说明,调用ExitProcess至少在用户态下有这些动作

1)除了调用ExitProcess的线程之外,其他线程均被结束,但线程使用的DLL不会接收到DLL_THREAD_DETACH事件(正常结束线程或释放DLL则会有DLL_THREAD_DETACH事件)!

2)所有被结束的线程均设置为有信号,这样意味着如果在某些地方调用WaitForSingleObject等待线程结束的,则会马上获得信号并结束等待

3)所有被加载的DLL,均会调用入库函数并接收DLL_PROCESS_DETACH事件,这样意味这在Delphi里,所有单元的finalization的代码会被执行,同时也会清理运行时相关环境(大部分是system.pas,sysinit.pas里的)

4)结束当前线程和进程,这里会调用系统内部的功能代码去释放一些被系统认为是系统的资源(各种句柄和被系统管理的内存等)

5)进程的状态从STILL_ACTIVE变为ExitCode,完成退出进程(但该进程其实在系统中仍然有相关的资源存在的,不然其他进程怎么获取到这个ExitCode呢?只有再进程最后一个句柄关闭时,该进程的对象才会被释放)

另外,如果在步骤1中被结束的线程中,如果在释放相关的DLL时又调用ExitProcess,也就是除了当前调用ExitProcess的线程,有其他线程也调用了ExitProcess,则会导致死锁。而如果有不是调用ExitProcess来结束进程,而是直接调用TerminateProcess,则相关的DLL不会被正常通知释放,也就是DLL的入口函数不会被以DLL_THREAD_DETACH事件调用,这样也意味着Delphi里,所有单元的finalization的代码不会被执行,运行时相关环境也不会被释放!

在DLL中调用ExitProcess很容易导致一些错误,因为逻辑上讲,调用ExitProcess的DLL本身也会被释放调用,一旦该DLL的运行环境被释放(相当于自己释放自己),那正在执行的释放过程会很容易出现内存溢出或导致系统资源未正常释放而报错。除非在调用ExitProcess前已经释放了其他DLL和自身的资源,这时候才能最大限度保证不出错,而一般较为复杂的源码结构所编译的DLL,想要正确释放资源也不是一件容易的事。

下面看一下ExitProcess的伪代码,帮助理解:

VOID
WINAPI
ExitProcess(
    UINT uExitCode
    )
{
    // 步骤 1和 步骤 2
    Status = NtTerminateProcess(NULL,(NTSTATUS)uExitCode);
    // 步骤 3
    LdrShutdownProcess();
    // 步骤 4,5....
    CsrClientCallServer();
    NtTerminateProcess(NtCurrentProcess(),(NTSTATUS)uExitCode);

}

此外可以调用ntdll的NtTerminateProcess函数结束进程,该函数直接进入内核态结束进程,会造成一些系统资源无法释放,用户态的资源更别想释放了,所以,如果是实在不想看到错误提示框,就调用该函数吧,谨慎使用!

时间: 2024-11-10 07:56:39

使用ExitProcess退出时为什么还会报运行时错误的相关文章

win7 64 下 VS2008 调试、退出时错误的解决

最近调试老程序的时候发现原来的VS2008会偶尔在调试C++程序的时候出现程序未响应的情况,开始还以为是个案,后来出现的频率越来越高完全影响心情啊!! 准备花时间解决一下这个问题.网上搜索没有发现任何有价值线索,于是决定用上绝招--安装盘修复,但结果依然是那样.准备用process monitor监测一下,发现信息太多基本不太可能一一人工分析. 在解决问题的时候还发现了一个问题.启动VS2008后,打开一个项目,不做任何修改点全部保存,然后关闭VS2008,此时VS2008会出现异常100%可重

os.waitpid()无法获取sys.exit()退出时的status code

[目的] 父进程使用os.waitpid()等待子进程退出,并检测子进程的exit code,以决定是否重启子进程. (常见的应用场景是:子进程接收外部命令,收到"stop"时退出所有进程,终止服务:收到"restart"时所有子进程退出,父进程重启所有子进程,以达到重启服务的目的). 这里面的关键点在于,子进程退出时设置exit code,父进程waitpid时获取该exit code,进而决定是否需要重启子进程. [问题] 子进程 ...#need restar

Qt 程序退出时断言错误——_BLOCK_TYPE_IS_VALID(pHead->nBlockUse),由setAttribute(Qt::WA_DeleteOnClose)引起

最近在学习QT,自己仿写了一个简单的QT绘图程序,但是在退出时总是报错,断言错误: 报错主要问题在_BLOCK_TYPE_IS_VALID(pHead->nBlockUse),是在关闭窗口时报的错: 先前考虑是析构函数有问题,重写并且排查相关变量并未发现问题. 根据报错问题又推测栈调用出现内存溢出,寻找程序中所有的链表和栈调用.未果. 最后用了最笨的方法,将构造函数中所有变量挨个遍历,最终确定问题出在Qt的setAttribute(Qt::WA_DeleteOnClose)这行代码上. 网上查询

WebView中音视频自动播放与退出时停止播放

背景: 项目需求是进入页面自动播放音频或者视频(非本地资源),页面关闭时音频或视频关闭.现在实现情况是:自动播放功能在有些手机上可以自动播放并有声音,有的手机上也播放但没有声音,当用户点击或者产生触发条件下才会有声音:退出关闭当前Activity,音频或视频并没有关闭,还在播放. 解决方法: 1.Activity退出时关闭音频或视频 重写Activity的onDestroy()方法,在方法里添加webView.destroy()方法. @Override protected void onDes

写一个循环,不断的问客户想买什么 ,当用户选择一个商品编号,就把对应的商品加入购物车 ,最终用户输入q退出时,答应购物车的商品

写一个循环,不断的问客户想买什么 ,当用户选择一个商品编号,就把对应的商品加入购物车 ,最终用户输入q退出时,答应购物车的商品products=[["Iphone8",68888],["MacpPro",14800],["Coffee",31],["小米",2499],["Book",80],["Nlke",799]]shopping_cart=[]print(".....商品

[UWP]在应用退出时弹出确认提示框

1. 需求 在应用退出时(点击右上角的关闭按钮)弹出一个确认按钮可以说是一个最常见的操作了,例如记事本的"你是否保存": 但这个功能在UWP上居然有点小复杂.这篇文章将解释如何实现这个功能. 2. CloseRequested 为了监视应用退出事件,我本来使用了CoreApplication.Exiting,但好像并不起作用,后来我就没再研究它的触发机制了.在Windows 10 Creators Update (15063)以后UWP提供了一个新的API:SystemNavigati

Android设置Activity启动和退出时的动画

业务开发时遇到的一个小特技,要求实现Activity启动时自下向上弹出,退出时自上向下退出. 此处不关注启动和退出时其他Activity的动画效果,实现方法有两种: 1.代码方式,通过Activity的overridePendingTransition接口, 即在startActivity时调用overridePendingTransition(R.anim.push_bottom_in, 0) 在finish时调用overridePendingTransition(0, R.anim.push

[转载]DllMain中不当操作导致死锁问题的分析--线程退出时产生了死锁

(转载于breaksoftware的csdn博客) 我们回顾下之前举得例子 case DLL_PROCESS_ATTACH: { printf("DLL DllWithoutDisableThreadLibraryCalls_A:\tProcess attach (tid = %d)\n", tid); HANDLE hThread = CreateThread(NULL, 0, ThreadCreateInDllMain, NULL, 0, NULL); WaitForSingleO

表空间正在热备份时关闭实例重启报错的重现和解决

最近一个客户的库在OPEN时报错需要恢复,发现原因为当时一个表空间正在热备份-->ALTER TABLESPACE TEST1 BEGIN BACKUP;  然后实例异常关闭(可能为ABORT或KILL SMON等进程,这里据说为存储直接关闭导致),然后重启时遇到此错误. 在ORACLE 10.2.0.1及11.2.0.4版本中重现了此错误,在这两个版本中同样的情况但是报错信息不太一样,具体情况如下: 10.2.0.1.0 版本表空间正在热备份时关闭实例重启报错的重现和解决: SQL> sel