当前位置:首页 > > 充电吧
[导读]STL跨平台调用会出现很多异常,你可以试试. STL使用模板生成,当我们使用模板的时候,每一个EXE,和DLL都在编译器产生了自己的代码,导致模板所使用的静态成员不同步,所以出现数据传递的各种问题

STL跨平台调用会出现很多异常,你可以试试. STL使用模板生成,当我们使用模板的时候,每一个EXE,和DLL都在编译器产生了自己的代码,导致模板所使用的静态成员不同步,所以出现数据传递的各种问题,下面是详细解释。


原因分析:
一 句话-----如果任何STL类使用了静态变量(无论是直接还是间接使用),那么就不要再写出跨执行单元访问它的代码。 除非你能够确定两个动态库使用的 都是同样的STL实现,比如都使用VC同一版本的STL,编译选项也一样。强烈建议,不要在动态库接口中传递STL容器!!

STL不一定不能在DLL间传递,但你必须彻底搞懂它的内部实现,并懂得为何会出问题。
微软的解释:
http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b172396
微软给的解决办法:
http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b168958

1、微软的解释:
大 部分C++标准库里提供的类直接或间接地使用了静态变量。由于这些类是通过模板扩展而来的,因此每个可执行映像(通常是.dll或.exe文件)就会存在 一份只属于自己的、给定类的静态数据成员。当一个需要访问这些静态成员的类方法执行时,它使用的是“这个方法的代码当前所在的那份可执行映像”里的静态成 员变量。由于两份可执行映像各自的静态数据成员并未同步,这个行为就可能导致访问违例,或者数据看起来似乎丢失或被破坏了。

可能不太好懂,我举个例子:假如类A

 

在动态连接库开发中要特别注意内存的分配与释放问题,稍不注意,极可能造成内存泄漏,从而访问出错。例如在某DLL中存在这样一段代码:

extent "C" __declspec(dllexport) 
void ExtractFileName( const std::string& path //!< Input path and filename.
, std::string& fname //!< Extracted filename with extension.
)
{
std::string::size_type startPos = path.find_last_of('\');
fname.assign(path.begin() startPos 1, path.end() );
}

在DLL中使用STL对象std::string,并且在其中改变std::string的内容,即发生了内存的重分配问题,若在EXE中调用该函数会出现内存访问问题。主要是:因为DLL和EXE的内存分配方式不同,DLL中的分配的内存不能在EXE中正确释放掉。

解决这一问题的途径如下:
一般情况下:构建DLL必须遵循谁分配就由谁释放的原则,例如COM的解决方案(利用引用计数),对象的创建(QueryInterface)与释放均在COM组件内部完成。在纯C 环境下,可以很容易的实现类似方案。


在应用STL的情况下,很难使用上述方案来解决,因此必须另辟蹊径,途径有二:
1、自己写内存分配器替代STL中的默认分配器。
2、使用STLport替代系统的标准库。

其实,上述问题在VC7及以后版本中,已得到解决,注意DLL工程和调用的工程一定要使用多线程DLL库,就不会发生内存访问问题。

 

 

一个很奇怪的问题:DLL中使用std::string作为参数结果出错 STL 这段时间,在工程中将一些功能封装成动态库,需要使用动态库接口的时候.使用了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

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

1.传递vector指针

2.传递const vector

究其原因:

是因为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的时候注意的。

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

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

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

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

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

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

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

 

 

总结:

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

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

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭