DLL中New和外部Delete以及跨DLL传递对象的问题

来源:互联网 发布:mac磁盘名称格式 编辑:程序博客网 时间:2024/05/05 07:26
不同的DLL中完全可能会维护不同的局部堆,这与编译器的实现有关。有些编译器可以选择使用进程共享的局部堆,但性能会受影响。 

    如果是不同的局部堆,当你在DLL中new时,是在DLL的堆中分配的;而当你在EXE中delete时,EXE会认为它是在EXE的局部堆中分配的,从而用EXE的堆信息去释放它,从而可能导致错误。具体情况与堆管理代码的实现有关。 

    最好为你的class或struct提供一个虚的free方法,在里面调用delete。不管是从EXE中分配的还是从DLL中分配的,都可以安全地用free方法释放,因为free是虚的,它的代码会和分配它的代码编译在同一个可执行体中。 

    我不赞成用引出类的方法提供功能,因为类成员的签名生成并没有一个标准,很难使用。 

    用DLL提供的类最好是只引出创建对象的函数,返回类型是一个“纯抽象类”指针,我说的“纯抽象类”指没有成员变量,没有非抽象方法的类。并且有一个公开的抽象的free方法负责释放。使用时调用创建函数创建一个(衍生类) 的对象并返回,然后调用对象的成员方法来完成操作。 

下面举两个最近遇到的例子。
1. vector<string>&,与其它类似的参数
错误的做法:以vector<string>&形式传递参数,用来接收数据,在DLL内对vector进行填充。这样做会导致vector在DLL外析构时发生内存指针失效异常。这类问题只发生在程序静态编译的情况下。
错误原因:vector在DLL通过pushback函数开辟了堆空间,析构时在DLL外进行内存释放。《Windows 核心编程》第5版19章 DLL编程有详细讲解。
正确的做法:以vector<string>*形式传递参数, 传递NULL指针到DLL,由DLL通过new开辟空间,能及填充内容。DLL提供释放接口函数类似 void destroy(vector<string>* pVector); DLL的调用者在对数据使用完毕后,调用些函数进行内存释放。

2. string,与其它在拷贝构造时会开辟空间的数据类型
错误的做法:通过传递形参提供数据给DLL BOOL IsPathExist(string strPath)。这样做会导致strPath在DLL函数IsPathExit退出时,调用string类的析构后发生内存指针失效异常。这类问题也只发生在程序静态编译的情况下。
错误原因:strPath在函数被调用时,通过拷贝构造被创建,但此过程是发生在DLL外的!
正确的做法:传递string& strPath,避免拷贝构造。
原创粉丝点击