现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

DLL中使用std::string作为参数结果出错

2015-07-28 11:27 工业·编程 ⁄ 共 2452字 ⁄ 字号 评论 1 条

这段时间,在工程中将一些功能封装成动态库,需要使用动态库接口的时候.使用了STL的一些类型作为参数.

比方string,vector,list.但是在使用接口的时候.

class exportClass

{

     bool dll_funcation(string &str);

};

//上面这个类只是一个形式,具体内容不写出来了.这个类被导出

当我在使用这个库的时候.这样写代码:

string str="":

exportClass tmp;

tmp.dll_function(str);

这个函数能成功调用.但是在函数里面会给这个数组附值.如果字符串太长,就会出错.函数调用能成功,但是一旦str资源需要释放的时候,资源就不能释放了,提示释放了错误的内存空间.

一点一点取掉这个函数的代码.最后就剩下

str="qadasdasdasdsafsafas";

还是出错误.

如果改成很短的字符串,就不会出错误.

在这个时候,只能尝试认为是字符串的空间太小

最终我修改成这样,错误消失了.希望错误真的是这个引起的

string str="":

str.resize(1000);

exportClass tmp;

tmp.dll_function(str);

  

今天写程序的时候要给一个模块的dll传递一个参数,由于参数数量是可变的,因此设计成了vector<string>类型,但调试过程中发现在exe中的参数传递到dll中的函数后,vector变成空的,改成传引用类型后,vector竟然变得很大,并且是无意义的参数。

对于这个问题,两种办法:

1.传递vector指针

2.传递const vector<TYPE>。

究其原因:

是因为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)的一种吧。

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

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

当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里...

模板+动态链接库的使用问题还很多. 要千万留心这个陷阱遍地的东西啊

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

总结:

字符串参数用char*,Vector用char**,

动态内存要牢记谁申请谁释放的原则。

目前有 1 条留言    访客:1 条, 博主:0 条

  1. 666 2019年04月25日 10:56 上午  @回复  Δ1楼 回复

    std::string 如果字符串长度少,是在栈分配内存,字符串多会在堆分配

给我留言

留言无头像?