首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

请教:当线程被强行结束时怎么释放堆上new的内存

2012-03-06 
请问:当线程被强行结束时如何释放堆上new的内存?通过dll的一个导出函数中创建了线程,在该线程的InitInstan

请问:当线程被强行结束时如何释放堆上new的内存?
通过dll的一个导出函数中创建了线程,在该线程的InitInstance初始化部分通过new分配了大量的C++对象以及Windows资源窗口等等。如果该函数正常调用,并且线程正常结束时在ExitInstance中通过delete以及DestroyWindow等等释放资源。
如果该函数已经被调用,可是线程还在执行中时,当用户非正常结束主程序,线程将被强行结束,主程序将终止,Dll最终会被释放。此时无法进入线程的ExitInstance中来释放资源,在VC的Debug窗口中提示内存泄露。由于该函数可以被多次调用,可能产生多个线程,多次调用将进一步加大了内存泄漏。
由于使用的是regular dll,无论如何在Dll被释放时会调用CWinApp::ExitInstance,我计划通过每次在函数中创建线程时,将所创建的对象以及窗口资源的句柄通过vector保存在theApp的内部,当线程正常结束时修改theApp的vector[i]为NULL,当整个Dll卸载时,判断相应的值,如果不为NULL就执行释放工作。在往vector注册时我通过CCriticalSection保证一致。
可是发现,在异常退出清理资源时,无法成功delete掉new出的东西,而且DestroyWindow也不能奏效,引发了ASSERT失败。通过检测发现:在调用CWinApp::ExitInstance之前,所有创建的线程均已经终止。
请问:
1 以上情况下,为什么无法delete掉堆上new出的东西?是通过同一个指针值访问的。窗口句柄也无效。
2 有没有办法监控线程,在异常终止之前能够保证释放资源。
谢谢

[解决办法]
MFC规则DLL中的CWinApp对象是一个全局变量,在卸载DLL的时候调用ExitInstance,不是每个线程结束都调用的。
线程中可以用try来捕获异常,释放资源。
[解决办法]
如果线程被强行终止,调用堆栈中所有函数中new的堆内存(对象)都没有机会释放了。

如果有可能还是要让线程通过event得到事件,自己终止
[解决办法]

探讨
如果线程被强行终止,调用堆栈中所有函数中new的堆内存(对象)都没有机会释放了。

如果有可能还是要让线程通过event得到事件,自己终止

[解决办法]
不同模块(dll,exe)分配内存可能在不同的heap上做的,这样你在exe中 delete在dll中分配的内存,delete还是试图在exe的堆上查找这个要被删除的内存,因此要失败

如果线程被TerminateThread结束,他是没有任何机会去释放东西的。因此好的多线程程序要尽量避免使用TerminateThread。所有的在线程内的操作都应该找一种可中止的方法,因此你可以通知线程自己结束自己,这样才安全。
引用楼主 fangxu1999 的帖子:
通过dll的一个导出函数中创建了线程,在该线程的InitInstance初始化部分通过new分配了大量的C++对象以及Windows资源窗口等等。如果该函数正常调用,并且线程正常结束时在ExitInstance中通过delete以及DestroyWindow等等释放资源。
如果该函数已经被调用,可是线程还在执行中时,当用户非正常结束主程序,线程将被强行结束,主程序将终止,Dll最终会被释放。此时无法进入线程的ExitInstance中来释放资源,在VC的Debug窗口中提示…

[解决办法]
可以考虑HOOK强行终止应用程序的API(如TerminateProcess)的方法来避免此事。

应该程序拦截到这个调用以后,就自己优雅终止所有线程的执行,然后退出运行。

热点排行