sizeof(std::unordered_map<int, int>)
的值在linux上gcc 4.6-4.9的不同gcc版本中似乎有所不同:
(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()
的{{1}}的二进制代码。该库是使用gcc 4.6编译的,因此假设Foo::val
从val
开始偏移了56个字节。
现在我编写了使用Foo
的程序。我写了
libfoo
我使用gcc 4.8构建我的程序。它假定#include <foo.h>
int bar() {
Foo foo;
return foo.getVal();
}
的大小为48个字节,因此仅为Foo对象分配unordered_map
。因此,48+sizeof(int)
访问对象外部的数据。
所以,我的问题是:
foo.getVal()
?事实上,问题只是分配适当的内存大小,因为unordered_map
字段的所有实际工作只发生在map
内。我认为我可以通过显式分配更多内存并进行新的放置来做一些原始指针魔术,但这似乎真的不可靠并且容易发生内存泄漏。libfoo.so
实现在gcc&lt; 4.9中仍然被认为是实验性的,因此其他非实验性标准类不会出现类似的问题吗? / LI>
请注意,链接到特定版本的libstdc ++似乎不是问题。问题在于计算应该分配多少内存。
答案 0 :(得分:2)
关于问题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
或者用指针或引用做某事时,你会三思而后行。