gcc版本

时间:2016-12-20 09:33:00

标签: c++ c++11 gcc

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

  • 4.6:56
  • 4.7:64
  • 4.8:48
  • 4.9&amp;更新: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()的{​​{1}}的二进制代码。该库是使用gcc 4.6编译的,因此假设Foo::valval开始偏移了56个字节。

现在我编写了使用Foo的程序。我写了

libfoo

我使用gcc 4.8构建我的程序。它假定#include <foo.h> int bar() { Foo foo; return foo.getVal(); } 的大小为48个字节,因此仅为Foo对象分配unordered_map。因此,48+sizeof(int)访问对象外部的数据。

所以,我的问题是:

  1. 有什么方法可以解决这个问题吗?例如,制作gcc 4.8使用gcc 4.6中的foo.getVal()?事实上,问题只是分配适当的内存大小,因为unordered_map字段的所有实际工作只发生在map内。我认为我可以通过显式分配更多内存并进行新的放置来做一些原始指针魔术,但这似乎真的不可靠并且容易发生内存泄漏。
  2. 我是对的,这是一种非正常的情况,可能是因为libfoo.so实现在gcc&lt; 4.9中仍然被认为是实验性的,因此其他非实验性标准类不会出现类似的问题吗? / LI>
  3. 如果不是,那么一般应该如何减轻这些问题呢?
  4. 请注意,链接到特定版本的libstdc ++似乎不是问题。问题在于计算应该分配多少内存。

1 个答案:

答案 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或者用指针或引用做某事时,你会三思而后行。