跨共享库边界分配和释放内存

use*_*404 6 c++ linux windows shared-libraries

在使用 Windows dll 时,我们应该限制 dll 边界内的内存分配/释放,因为 dll 可能使用自己的堆。所以我们有从 dll 导出分配器和自由函数。

IsomeInterface* getObject();
void freeObject(IsomeInterface *object);
Run Code Online (Sandbox Code Playgroud)

这样,对象的创建和删除将驻留在 dll 中。

linux上的共享库是否也存在这个问题?在处理共享库 (.so) 时,我们是否还需要注意在共享库中保持分配/解除分配。我在下面做了一些快速试用,它适用于 linux。相同的示例不适用于 windows dll(如果 exe 和 dll 都使用 /MD 编译以使用相同的堆,它将适用于 windows dll)。

std::vector<int> vec;
vec.push_back(42);
PassAVector(vec);
Run Code Online (Sandbox Code Playgroud)

其中PassAVector驻留在共享库

void PassAVector(std::vector<int> &vec)
{
     vec.push_back(1);  // These would cause reallocation
     vec.push_back(2);
     vec.push_back(3);
     vec.push_back(4);
     vec.push_back(5);
}
Run Code Online (Sandbox Code Playgroud)

这是否意味着 unix 上的共享库与可执行文件共享堆(相当于 Windows 上的 /MD 开关)?

是否可以在 linux 上编译(某些编译器标志)共享库 (.so) 或可执行文件,以便它们开始使用不同的堆(Windows 上的 /MT 开关)并且这个问题浮出水面?

编辑:发现似乎表明只要编译器是 gcc,就可以跨边界传递 STL。

yug*_*ugr 4

只要您坚持使用 Glibc 或其他“正常”分配器(jemalloc、tcmalloc 等),堆状态将由所有库共享,因此您将能够释放在malloc您想要的任何地方分配的内存。

理论上是可以绕过这个的。例如,某些库可能与malloc/ 的自定义实现链接free(通过 的符号脚本欺骗-Bsymbolic),它有自己的私有堆,因此不会与程序的其他部分很好地交互。但我在现实生活中从未见过这样的事情。

STL 容器基于malloc/free因此也可以跨库边界传递/修改它们。当然,不同的库可以使用不同的编译器和不同的不兼容版本的 STL(例如 libstdc++、libcxx 等)进行编译,但它们的 C++ 容器类型会有所不同,并且编译器根本不允许您将它们传递给不兼容的模块。