繁体   English   中英

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

[英]Why do I get a warning for an unaligned pointer but not a reference

我有一个项目要从 32 位 Windows 移植到 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 帮助条目在此处 __unaligned帮助表明不注意此警告将导致在 Itanium 处理器上引发异常。 对 MSDN 的进一步搜索表明可能存在围绕未对齐引用的问题 虽然这可能不会给我当前的用户带来问题,但如果 Itanium 架构在未来得到更广泛的使用,我可能会遇到支持噩梦。 现在计划为所有使用压缩结构的函数添加特定的包装器,以避免指针和 __unaligned 关键字。

引用和指针几乎是一样的东西(可以这么说),所以从安全的角度来看,它没有什么不同。 这可能更多是一种疏忽和/或编译器不太关心引用,因为它们不能在 C++ 环境之外传递(尽管我倾向于认为这只是一种疏忽)。

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

多线程也存在问题,因为未对齐的访问可能不会自动更新数据。 当然,对于线程之间共享的数据,您应该使用std::atomic或类似方法。

x86 完全能够从未对齐的地址读取double精度值。 我认为 Itanium 不是,但我怀疑您无论如何都不会使用该处理器,从统计上讲。 其他较旧的体系结构(例如 Alpha)可能会在读取未对齐的内存时出现问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM