DLL-初始化vector并传引用到DLL中,DLL中为该引用添加节点,vector内存释放时会报堆栈错误,想搞明白原因
内存是在dll中申请,但没有动态申请,直接赋值给vector,程序结束时并没有手动释放,好像和runtime library参数设置有关系
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
内存是在dll中申请,但没有动态申请,直接赋值给vector,程序结束时并没有手动释放,好像和runtime library参数设置有关系
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(3)
这个问题其实挺好避免的,说白了就是不要一个模块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),会造成可执行模块中的静态数据成员不同步,这个动作可能会导致引发访问冲突或数据出现丢失和其它不可预知的结果。
如果是在dll进行new操作,最好就在dll中进行释放操作