请选择 进入手机版 | 继续访问电脑版

OpenWrt

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 4291|回复: 3

vector作为参数传递到dll问题

[复制链接]

104

主题

173

帖子

883

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
883
发表于 2014-8-1 13:02:04 | 显示全部楼层 |阅读模式

dll库传给exe的是一个vector指针,用完之后exe 中删除。

这个过程中首先就是在exe中将其vector指针转为相应指针再获取vector中相应的数据问题,始终都获得不了正确的数据,

要么就是一些非法的数据;

另一个问题就是delete这个指针时候会产生相应异常(针对这个问题的思考:如果EXE和DLL都链接到DLL的C/C++运行期库,那么代码将能够很好地运行.但是,如果两个模块中的一个或者两个链接到静态C/C++运行期库,那delete的操作就会失败.)。

这叫一个折腾的纠结啊。搜罗了一些网络资料以备以后的参考学习:

(1)对于STL,在DLL中使用的时候,往往存在这些问题,在网络上搜集了下,这些都是要平时使用STL的时候注意的。


引用http://www.hellocpp.net/Articles/Article/714.aspx

template  是个好东西啊 . 经典的 stl . 强悍的boost. 还有我自己写的那个 ------- 该死的 ------- 资源管理器.
dynamic link也是个好东西啊. 在windows下叫dll,
在unix下叫so (share object) .
它能省下很多重新发布软件带来的麻烦.但是当template  遭遇到dynamic link 时候,
很多时候却是一场恶梦.现在来说说一部分我已经碰到过的问题. 问题主要集中在内存分配上.
1>       拿STL来说, 自己写模板的时候,很难免就用到stl. stl的代码都在头文件里.  那么表示着内存分配的代码.

          只有包含了它的cpp 编译的时候才会被决定是使用什么样的内存分配代码.
          考虑一下: 当你声明了一个vector<> . 并把这个vector<>交给一个 dll里的代码来用. 用完后, 在你的程序里被释放了.   
          那么如果你 在dll里往vector里insert了一些东西. 那么这个时候insert 发生的内存分配的代码是属于dll的.
          你不知道这个dll的内存分配是什么. 是分配在哪里的.  而这个时候.释放那促的动作却不在dll里.....
          同时. 你甚至无法保证编译dll的那个家伙使用的stl版本和你是完全一样的..>     
          如此说来, 程序crash掉是天经地义的....        
         
         对策: 千万别别把你的stl 容器,模板容器在 dll 间传来传去 .  记住string也是....
2>       你在dll的某个类里声明了一个vector之类的容器.  而没有显式的写这个类的构造和析构函数. 那么问题又来了.     

         你这个类肯定有操作这vector的函数. 那么这些函数会让vecoter<>生成代码. 这些代码在这个dll里都是一致的.
         但是别忘了.你没有写析构函数...... 如果这个时候, 别人在外面声明了一个这样的类.然后调用这个类的函数操作了这个vector
         ( 当然使用者并不知道什么时候操作了vector) .  
         它用完了这个类以后. 类被释放掉了. 编译器很负责的为它生成了一份析构函数的代码...... 听好了.
         这份代码并不是在 dll里 ... . 事情于是又和1>里的一样了.... crash ......(可能还会伴随着迷茫.....)     
        
         对策: 记得dll里每个类,哪怕式构造析构函数式空的. 也要写到cpp里去. 什么都不写也式很糟糕的.....同时,
                   更要把任何和内存操作有关的函数写到 .cpp 里...
3>     以上两个问题似乎都是比较容易的-----只要把代码都写到cpp里去, 不要用stl容器传来传去就可以了.   那么第三个问题就要麻烦的多.   

         如果你自己写了一个模板, 这个模板用了stl 容器..........   这个时候你该怎么办呢? 
         显然你无法把和内存分配相关的函数都写到.cpp里去 . template的代码都必须放到header file里.....   


        对策:  解决这个问题的基本做法是做一个stl 内存分配器 , 强制把这个模板里和内存分配相关的放到一个.cpp里去.
                  这个时候编译这个cpp就会把内存分配代码固定在一个地方: 要么是dll. 要么是exe里... 模板+动态链接库的使用问题还很多.
                  要千万留心这个陷阱遍地的东西啊


另外,對於這種問題的解決辦法,下面3种可行办法:
1. 传递vector指针
2. 传递const vector
3. 儘量不使用stl作為dll間的傳遞參數,使用指針會更好點

究其原因:是因为vector在exe和dll之间传递的时候,由于在dll内可能对vector插入数据,而这段内存是在dll里面分配的,

       exe无法知道如何释放内存,   从而导致问题。而改成const类型后,编译器便知道dll里不会改变vector,从而不会出错。
       或者可以说这是"cross-DLL problem."(This problem crops up when an object is created using new in one dynamically
       linked library (DLL) but is deleted in a different DLL)的一种吧。

(2) 从一个可执行程序中输出模板实例,在另一个可执行程序中引入此实例。

       例如:MyLibrary.DLL将vector <MyClass> 指针回传给MyProgram.EXE中的一个函数,

      需要在MyLibrary.DLL中输出MyClass类和vector <MyClass> 。在MyProgram.EXE中引入它们后。

      就可以得到MyLibrary.DLL中静态数据成员的一份Copy了。

这个是解决我这个问题的挺不错的方法,但是并为给予采纳和验证。毕竟为了保险起见最终还是选择了数组传递数据,

但是还是要给予的原则是谁创建谁释放。否则还是会出问题我这里即便是调用delete[ ]objArray;这里的delete的并不知道要删除多大的内存,

而这个要删除多大的内存信息是在dll中保存着的,那个dll中的delete才知道。

DLL中分配的内存DLL要负责释放!(一个模块分配的内存要在同一个模块中释放!)

***************************************************************************************************************************

微软关于这类问题的解释:

You may experience an access violation when you access an STL object through a pointer or reference in a different DLL or EXE

http://support.microsoft.com/default.aspx?scid=KB;en-us;q172396

How to export an instantiation of a Standard Template Library (STL) class and a class that contains a data member that is an STL object

http://support.microsoft.com/default.aspx?scid=KB;en-us;q168958


这个讲解也不错:http://blog.csdn.net/lewutian/article/details/6786193



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|OpenWrt系统应用网 ( 京ICP备14035914号-1

GMT+8, 2021-8-5 19:01 , Processed in 0.055964 second(s), 32 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表