gpt4 book ai didi

c++ - 跨 gcc 版本的 unordered_map 大小不同

转载 作者:搜寻专家 更新时间:2023-10-31 02:13:31 45 4
gpt4 key购买 nike

sizeof(std::unordered_map<int, int>) 的值在 linux 上 gcc 4.6—4.9 周围的不同 gcc 版本中似乎有所不同:

  • 4.6: 56
  • 4.7: 64
  • 4.8: 48
  • 4.9 及更高版本:56

( test code on coliru )(其他专业同理)

当将使用不同 gcc 版本编译的库链接在一起时,这显然会导致内存访问问题。

也就是说,我现在面临的一个问题是一个图书馆,比如 libfoo , 这暴露了一些 class Foo作为它的界面。也就是说,图书馆提供了 foo.h头文件:

class Foo {
std::unordered_map<int, int> map;
int val;
public:
Foo(): val(42) {}
int getVal();
};

并且还提供编译库libfoo.so包含 Foo::getVal() 的二进制代码访问 Foo::val .该库是用 gcc 4.6 编译的,因此假定 valFoo 偏移了 56 个字节开始。

现在我编写使用 libfoo 的程序.我写

#include <foo.h>    
int bar() {
Foo foo;
return foo.getVal();
}

我用 gcc 4.8 构建我的程序。它假设 unordered_map大小为 48 字节,因此仅分配 48+sizeof(int)对于 Foo 对象。结果,foo.getVal()访问对象外部的数据。


所以,我的问题是:

  1. 有什么办法可以解决这个问题吗?例如,使 gcc 4.8 使用 unordered_map来自 gcc 4.6?事实上,问题只是allocationg适当的内存大小,因为所有实际工作都与map有关字段仅在 libfoo.so 内发生.我认为我可以通过显式分配更多内存并进行新的放置来实现一些原始指针魔术,但这似乎真的不可靠并且容易出现内存泄漏。
  2. 我说的对吗,这是一种不寻常的情况,可能是因为 unordered_map在 gcc <4.9 中实现仍然被认为是实验性的,因此其他非实验性的标准类不会出现类似的问题吗?
  3. 如果不是,那么一般应如何缓解此类问题?

请注意,链接到特定版本的 libstdc++ 似乎不是问题;问题是计算应该分配多少内存。

最佳答案

关于问题1:

我会使用以下包装器:

constexpr int DesirableFooSize = 60;
constexpr bool FooTooSmall = sizeof(Foo) < DesirableFooSize;

class FooWrapper final : private Foo {
std::enable_if<FooTooSmall, std::array<int8_t, DesirableFooSize - sizeof(Foo)>>::type x;
public:
using Foo::getInt;
using Foo::Foo;
Foo* getFooPointer() {
return this;
}
Foo& getFooReference() {
return *this;
}
};

并且您程序中的所有代码都应该使用 FooWrapper 而不是普通的 Foo。这将保证您始终为每个 Foo 对象分配恰好 60 个字节,永远不会忘记释放这些额外的内存,并且额外的内存不可访问。 Private 继承和显式转换函数是有意写在这里的,让你在将 FooWrapper 转换为 Foo 或做一些事情时三思而后行指针或引用。

关于c++ - 跨 gcc 版本的 unordered_map 大小不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41238962/

45 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com