当使用 windows dll 时,我们应该将内存分配/释放限制在 dll 边界内,因为 dll 可能使用自己的堆。
所以我们有从 dll 导出分配器和释放函数。
IsomeInterface* getObject();
void freeObject(IsomeInterface *object);
这样,对象的创建和删除将驻留在 dll 中。linux上的共享库是否也存在这个问题?在处理共享库(.so)时,我们是否还需要注意在共享库中保持分配/解除分配。
我在下面做了一些快速试用,它可以在 linux 上运行。相同的示例不适用于 windows dll(如果 exe 和 dll 都使用/MD 编译以使用相同的堆,它将适用于 windows dll)。
std::vector<int> vec;
vec.push_back(42);
PassAVector(vec);
在哪里 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);
}
这是否意味着 unix 上的共享库与可执行文件共享堆(相当于 Windows 上的/MD 开关)?是否可以在 Linux 上编译(一些编译器标志)共享库(.so)或可执行文件,以便它们开始使用不同的堆(Windows 上的/MT 开关)并且这个问题浮出水面?
编辑:找到 this只要编译器是 gcc,这似乎表明跨边界传递 STL 是可以的。
最佳答案
只要您坚持使用 Glibc 或其他“普通”分配器(jemalloc、tcmalloc 等),堆状态将由所有库共享,因此您将能够释放使用 malloc
分配的内存。任何你想的地点都可以。
理论上是可以绕开的。例如,某些库可能与 malloc
的自定义实现链接。/free
(通过 -Bsymbolic
的符号脚本技巧)它有自己的私有(private)堆,因此不会与程序的其他部分很好地交互。但我在现实生活中从未见过这样的事情。
STL 容器基于 malloc
/free
因此也可以跨库边界传递/修改它们。当然,不同的库可以用不同的编译器和不同的不兼容版本的 STL(例如 libstdc++、libcxx 等)编译,但它们的 C++ 容器类型会不同,编译器根本不允许您在不兼容的模块之间传递它们。
关于c++ - 跨共享库边界分配和释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64574662/