首页 文章

输入punning,char []和解除引用

提问于
浏览
5

我有一个旨在存储用户定义数据(即来自插件)的结构 . 它有一个具有给定最大大小的 char[] 来存储该数据 .

struct A
{
    // other members omitted
    // data meant to be type punned, only contains PODs
    char data[256];
};

然后是一个示例用户结构,它具有从 A 强制转换自身的静态函数 .

struct B
{
    int i;
    double d;

    static B& FromA_ref(A& a)
    {
        // static_assert that sizeof(B) < sizeof(A::data)
        return * reinterpret_cast<B*>(a.data);
    }
};

我用 g++ -O3 -std=c++0x -Wall -o test test.cpp (GCC 4.6.1)编译 .

这会触发 dereferencing type-punned pointer will break strict-aliasing rules 警告 . 我认为这样就行了,因为我使用 char[] 作为存储,我认为它将遵循与 char* 相同的规则 . 我觉得很奇怪,你不是吗?好吧,...我可以继续前进.1805664 .

现在让我们考虑以下方法:

struct B
{
    ....
    static B* FromA_ptr(A& a)
    {
        // static_assert that sizeof(B) < sizeof(A::data)
        return reinterpret_cast<B*>(a.data);
    }
}

由于我在这里没有取消引用任何内容,GCC不会输出任何警告 . 当我稍后使用指针 B 时也不会这样做 .

A a;
auto b = B::FromA_ptr(a);
b->i = 2; // no warnings.

But is it safe to do so ? 我觉得我一直在解决问题而不是解决问题 . 对我来说 -> 仍然以某种方式取消引用该变量 .

或者,有没有更好的方法来实现这种效果? I.E.从另一个结构中的存储中获取一个可修改的引用(或指针)? (由于定义了 A 并且某些类型可能通过插件添加时未知,因此联合将无法工作, memcpy 会强制我来回复制数据,尽管它似乎是唯一安全的方式所以远)

1 回答

  • 4

    答案是否定的,不安全(见SO question

    GCC将假设指针不能别名 . 例如,如果你通过一个分配,然后从另一个读取,GCC可以作为优化,重新排序读取和写入 - 我已经看到这发生在 生产环境 代码中,调试是不愉快的 . 对于所使用的类型,属性((may_alias))可能是最接近禁用特定代码段假设的 .

相关问题