在使用windows dll时,我们应该将内存分配/释放限制在dll边界内,因为dll可以使用自己的堆。所以我们有从dll导出分配器和自由函数。
IsomeInterface* getObject();
void freeObject(IsomeInterface *object);这样,对象的创建和删除将驻留在dll中。
linux上的共享库也存在这个问题吗?在处理共享库(.so)时,我们还需要注意在共享库中保持分配/释放。我在下面做了一些快速试用,它在linux上工作。同样的例子不适用于windows dll (如果用/MD编译的exe和dll都使用相同的堆,它将适用于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开关)?
有没有可能编译(一些编译器标志)共享库(.so)或linux上的可执行文件,使它们开始使用不同的堆(windows上的/MT开关),并且这个问题浮出水面?
编辑:找到了this,它似乎建议跨边界传递STL,只要编译器是gcc就可以了。
发布于 2020-11-01 00:37:15
只要你坚持使用Glibc或者其他“普通”的分配器(jemalloc,tcmalloc等)堆状态将由所有库共享,因此您将能够使用malloc在您想要的任何地方释放分配的内存。
从理论上讲,有可能绕过这一点。例如,一些库可能链接到malloc/free的自定义实现(通过-Bsymbolic的符号脚本技巧),它有自己的私有堆,因此不能与程序的其他部分很好地交互。但我在现实生活中从未见过这样的事情。
STL容器基于malloc/free,因此也可以跨库边界传递/修改它们。当然,不同的库可以使用不同的编译器和不同的STL不兼容版本(例如libstdc++、libcxx等)进行编译。但是它们的C++容器类型是不同的,并且编译器不允许您在不兼容的模块之间传递它们。
发布于 2020-11-03 16:04:42
在C++中,更改堆的常规方法是重载全局操作符new/delete。
在Windows中,这种重载仅限于特定的dll,因此您会遇到问题。
在Linux中,重载的全局运算符通常是真正的全局运算符-因此第一个全局运算符获胜,但如果您确实希望在其中包含特定的堆,则可以实现这一点(然后您需要导出分配和释放函数):
https://stackoverflow.com/questions/64574662
复制相似问题