我有一个旨在存储用户定义数据(即来自插件)的结构 . 它有一个具有给定最大大小的 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 回答
答案是否定的,不安全(见SO question)