通过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之前,所有创建的线程均已经终止。
请问:
以上情况下,为什么无法delete掉堆上new出的东西?是通过同一个指针值访问的。窗口句柄也无效。
有没有办法监控线程,在异常终止之前能够保证释放资源。
谢谢

解决方案 »

  1.   

    MFC规则DLL中的CWinApp对象是一个全局变量,在卸载DLL的时候调用ExitInstance,不是每个线程结束都调用的。
    线程中可以用try来捕获异常,释放资源。
      

  2.   

    如果线程被强行终止,调用堆栈中所有函数中new的堆内存(对象)都没有机会释放了。如果有可能还是要让线程通过event得到事件,自己终止
      

  3.   

    或者主线程里最后return之前加一句WaitForSingleOjbect(hChildThread, INFINITE); 等待子线程结束后再退出。
      

  4.   

    不同模块(dll,exe)分配内存可能在不同的heap上做的,这样你在exe中 delete在dll中分配的内存,delete还是试图在exe的堆上查找这个要被删除的内存,因此要失败如果线程被TerminateThread结束,他是没有任何机会去释放东西的。因此好的多线程程序要尽量避免使用TerminateThread。所有的在线程内的操作都应该找一种可中止的方法,因此你可以通知线程自己结束自己,这样才安全。
      

  5.   

    ExitInstance是整个进程结束,卸载dll时调用,所以我将线程所申请的资源记录了下来,以备在异常退出时有机会delete。然而在异常退出时,这个delete操作却无法得以实现,引发了断言失败。不知该如何处理了。
    对于线程中用try来捕获异常,我看主要是线程执行过程内部出现的异常情况,当外部用户强行结束进程,进而终止了线程的运行是无法捕获的吧。
    我的线程是一个GUI线程,主要用来显示其他后台线程的执行状况信息的,该GUI线程中申请了许多资源,如果按照正常的执行逻辑能够完成任务,不会抛出异常信息的,也就不能try任何东西了啊。
    还请指教。
      

  6.   

    可以考虑HOOK强行终止应用程序的API(如TerminateProcess)的方法来避免此事。应该程序拦截到这个调用以后,就自己优雅终止所有线程的执行,然后退出运行。
      

  7.   

    这一点我可能没有讲清楚。我的exe仅仅是调用了该Dll的一个导出函数doSomething(),所有的功能实现、资源分配释放工作均交给dll来做了。所以应该算是在同一个模块上面分配的吧?而且我用了
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    据说是在模块之间切换,只是不晓得有什么作用罢了,能否说明一下啊。谢谢这里仍然是同样的问题了,线程本身是“没有任何机会去释放东西的”,我们能不能在线程的外部,通过其他手段来释放这些东西呢?CWinApp::ExitInstance是肯定要执行的,所以我想在这里来释放东西,可是不成功。
    请问问题出在哪里?或是有没有其他的时机来这些释放资源呢?虽然说是外部用户不正常操作引起的,可是我看着Debug窗口中的那一堆泄漏报告,很不爽。我希望这个Dll是一个自包含的东西。有没有办法能够解决啊?谢谢了
      

  8.   

    我的理解是不会内存泄漏的,因为APP退出,一切都GAME over聊,APP申请的内存,一定会还给系统。(找个还是强制性的还)