在 DLL 中用 new 来创建宿主程序中的对象,然后把这个对象指针保存到宿主程序,当 DLL 被卸载后,凡是涉及到这个指针的调用都会报错,包括 delete 这个指针也会有错。
分析原因,因为new/delete使用的是局部堆(当然这与编译器可能也有关,但至少M$的编译器应该是这样的),也就是说不同的DLL虽然共享一个地址空间,但完全可能会维护不同的局部堆(堆分段),这与编译器的实现有关。有些编译器可以选择使用进程共享的局部堆,但性能会受影响。
如果是不同的局部堆,当你在DLL中new时,是在DLL的堆中分配的;而当你在EXE中delete时,EXE会认为它是在EXE的局部堆中分配的,从而用EXE的堆信息去释放它,从而可能导致错误。具体情况与堆管理代码的实现有关。
解决办法:
1、为class或struct提供一个虚的create/free方法,在里面调用new/delete。不管是从EXE中分配的还是从DLL中分配的,都可以安全地用create方法创建/free方法释放,因为create/free是虚的,它的代码会和分配它的代码编译在同一个可执行体中。
2、用globalalloc()和globalfree()代替new和delete。
3、用动态库版本的c run-time library可以解决这个问题。
在project->setting->c/c++->category中选code generation,然后在use run-time library中选debug multithreaded。
4、重载new/delete操作符。