跨DLL边界的向量内存重定位

4

这个问题与SO中名字相似的问题不是重复的

众所周知,如果DLLs被静态链接(/MT标志在MSVC中),分配内存的DLL必须释放它;否则内存释放会导致运行时错误。

问题如下:

  • 我在DLL中分配了一个std::vector,称为A。
  • A将向DLL B传递向量。
  • DLL B插入数据到向量中。
  • 现在,如果DLL A试图销毁向量,则会遇到错误。

我已经发现,如果在将向量传递给B之前使用std::vector::reserve,使向量足够大以容纳数据并防止内存重新分配 - 通常在项目插入期间发生 - 那么在尝试销毁向量时,我就不会在A中获得错误信息。看起来,如果进行内存重新分配,B会为其自己的堆分配向量。我的推理错了吗?我该如何防止这种情况发生?


2
避免使用C++运行时的静态链接。 - Serge
1
另一个选项是使用Windows堆覆盖此向量的分配器。 - Serge
@Serge,我必须使用静态链接以制作独立的可执行文件。你知道任何这样的自定义分配器的例子吗?我之前曾经尝试编写自定义分配器,但并不容易。谢谢。 - Ahmad Siavashi
你已经在使用一个DLL,这与你关于独立可执行文件的说法相矛盾。很遗憾,我不知道有没有这样的文件。如果需要的话,我会在互联网上搜索。 - Serge
@Serge 使用DLL并不意味着可执行文件无法运行。它实际上可以在没有它们的情况下正常运行。所谓独立运行是指不强制用户在安装前/后安装C++运行时。是的,我已经搜索过了,但关于“自定义分配器”的材料要么太啰嗦,要么与此无关。顺便问一下,为什么我需要避免静态链接? - Ahmad Siavashi
因为 DLL 和 SO 的目的是使 RAM 使用更加高效。安装的便利性不在于安装程序应该复制到目标系统的文件数量,而在于对用户的透明度,即您的 DLL 安装程序应该安装所有必要的依赖项。你认为你的 DLL 是唯一一个在目标系统上使用 C++ 的吗? - Serge
1个回答

3
最简单的解决方法是将vector隐藏在从dll暴露的方法中,这样您就可以在其他dll中获取const vector进行查看,但不能修改它。然后,在dll B中创建一个新函数,代表调用者将条目添加到向量中。
因此,您的vector将在所有修改中保持隐藏在dll B中。

2
如果你要这么做,那么有一个“影子向量类”使用你提到的 DLL B 中的函数,是不是更有意义呢?也就是说,对于向量类的用户来说,它看起来就像是一个普通的向量。 - 0xC0000022L
@0xC0000022L 你的想法很棒。谢谢。 - Ahmad Siavashi
我打算将你们的想法混合在一起实现。非常感谢你们。如果我遇到任何困难,我会编辑我的问题,以便那些可能会遇到相同问题的人能够更好地了解。 - Ahmad Siavashi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接