当前位置:首页 > 芯闻号 > 充电吧
[导读]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**,

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

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

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭