您的位置:首页 > 编程语言 > C语言/C++

C++Vector的使用误区

2013-06-05 10:30 148 查看


初始化vector并传引用到DLL中,DLL中为该引用添加节点,vector内存释放时会报堆栈错误,原因?

这个问题其实挺好避免的,说白了就是不要一个模块new,另一个模块delete,不要认为你的vector的节点数据在栈上,vector的本质就是一个变长数组,怎么会在栈上呢,数据肯定是在堆上的,这样你就是在dll中申请的存储,在主程序里面释放的存储,出错很正常。

原因简要的分析一下:

1:像你说的一样,和runtime library的设置有关系,如果你设定为静态链接的方式,那么每一个模块都会有一个CRT堆,CRT堆是在可执行模块的入口点分配的@内存检测模块的实现中dll模块本身的堆空间创建方式类似,CRT堆和进程默认的堆空间是不交叉的,但是在一个线性的地址空间,在访问不同的模块数据时候,通过地址偏移可以很方便的进行访问。

2:如果你采用静态链接的方式,每一个可执行模块都会创建自己的CRT堆,在模块内部进行new和delete操作的时候,都是在CRT堆上进行的,这样不会出错,可是你的Vector的push操作是在dll内部,这时候很有可能已经发生了一次内存申请操作(可能vector的空间不足以存储新数据,所以进行新的存储申请,将旧数据进行一次拷贝,这时候申请的存储是在dll模块的CRT堆上,而不是在进程默认堆上),Vector的内存释放操作却是在dll外部,形成这种情况:
在dll的CRT堆上申请的空间,却在主程序内部释放空间,即使使用的new和delete是契合的,也有可能出问题。

3:解决方案,修改链接方式为动态连接,也就是DLL CRT的方式,这种方式下CRT堆只会创建一份,也就是主可行性模块加载的时候创建的那一份,在同一个模块申请释放存储自然不会出错。
简单的讲把vector传入到dll中后,添加节点时,在dll中会进行一些内存分配,当vector析构时,由于申请和释放不是相同模块,这会导致vector不知道如何正确释放dll中分配的内存。

还有一个问题更严重一些,一般比较隐蔽。比如标准C++库中的大多数类都直接或间接使用静态数据。由于这些类通过模板实例生成的,每个映像包含一个给定的类的静态数据成员的副本。当你在dll中使用或更改静态数据成员时,(由于该静态成员的代码驻留在可执行映像中,比如EXE),会造成可执行模块中的静态数据成员不同步,这个动作可能会导致引发访问冲突或数据出现丢失和其它不可预知的结果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: