为什么我会收到未对齐指针但不是引用的警告

时间:2013-06-17 11:48:41

标签: c++ 32bit-64bit memory-alignment

我有项目我从32位窗口移植到64位,其中包括可简化如下的代码;

void FuncA(double &x)
{
    x = 0;
}

void FuncB(double *x)
{
   *x = 0;
}

#pack(1)

struct 
{
   char c;
   double x;
} MyStruct;

#pack();

void MyFunc()
{
   MyStruct M;
   FuncA(M.x);  // This is OK
   FuncB(&M.x); // This generates a warning C4366
}

在针对64位的VS2010 SP1下进行编译时,使用压缩结构的成员调用FuncB会生成以下警告;

警告C4366:一元'&'的结果运营商可能未对齐

而调用FuncA却没有。我原以为这两种情况都会编译成几乎相同的代码。引用在某些方面比对等指针更安全吗?或者MSVC根本不发出警告应该在哪里?该项目需要维护结构包装,因此我的选择是将FuncB更改为

 void FuncB(__unaligned double *x)
{
   *x = 0;
}

或在所有这些情况下简单地使用FuncA。后者会更好,因为它更便携,但我想知道它是否会起作用,或者在参考案例中缺少警告只是编译器中的一个缺点。

修改:此错误的Microsoft帮助条目为here__unaligned帮助表明,如果不注意此警告,将导致在Itanium处理器上抛出异常。进一步在MSDN周围进行拖网示意there may be issues surrounding unaligned references。虽然这可能不会给我当前的用户带来问题,但如果Itanium架构在未来得到更广泛的使用,我可能会设置一个支持噩梦。 Plan现在是为使用压缩结构的所有函数添加特定包装器,以避免使用指针和__unaligned关键字。

1 个答案:

答案 0 :(得分:8)

参考和指针几乎是一回事(在引擎盖下,可以这么说),所以从安全角度来看,它并没有什么不同。它可能更多的是疏忽和/或编译器不太关注引用,因为它们不能在C ++环境之外传递(尽管我倾向于认为它是' ;只是一个疏忽)。

也可能是编译器更关注指针,因为指针更有可能用于性能,您希望迭代一系列double值(例如,通过分配更多的空间) struct本身使用,并在其后存储更多的double值 - 你不能用引用来做到这一点。由于未对齐访问至少比对齐访问慢,这可能会对性能产生影响,并且在某些系统中,它会导致操作系统陷阱,它将“修复”"未对齐的访问(以比普通对齐访问速度慢的几个命令的速度),或操作系统只是说"你的程序导致了一个未对齐的访问,我杀了它"。

多线程也存在问题,因为未对齐访问可能无法以原子方式更新数据。当然,您应该使用std::atomic或类似的线程来共享数据。

x86完全能够从未对齐的地址读取double。我认为Itanium不是,但从统计学角度来说,我怀疑你还没有使用过该处理器。其他较旧的架构,如Alpha可能在读取未对齐的内存时遇到问题。