如何解决跨共享库边界分配和取消分配内存
在使用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等),堆状态将被所有库共享,因此您将能够释放用{{1} }到任何地方。
从理论上讲,有可能避免这种情况。例如,某些库可能与malloc
/ malloc
的自定义实现相关联(通过free
的符号脚本骗术),该库具有自己的私有堆,因此无法与该库的其他部分很好地交互您的程序。但是我在现实生活中从未见过这样的事情。
STL容器基于-Bsymbolic
/ malloc
,因此也可以跨库边界传递/修改它们。当然,可以使用不同的编译器和不兼容的STL版本(例如libstdc ++,libcxx等)来编译不同的库,但是它们的C ++容器类型将有所不同,并且编译器根本不允许您在不兼容的模块之间传递它们。
在C ++中,更改堆的通常方法是使全局运算符new / delete重载。
在Windows中,重载仅限于特定的dll,因此您会遇到问题。
在Linux中,重载的全局运算符通常是真正的全局-因此第一个赢了,但是如果您确实希望在它们中使用特定的堆,则可以实现这一目标(然后需要导出的分配和自由函数):
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。