Sma*_*acL 10 c++ memory-alignment 32bit-64bit
我有项目我从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
}
Run Code Online (Sandbox Code Playgroud)
在针对64位的VS2010 SP1下进行编译时FuncB,使用压缩结构的成员进行调用会生成以下警告;
警告C4366:一元'&'运算符的结果可能是未对齐的
虽然打电话FuncA没有.我原以为这两种情况都会编译成几乎相同的代码.引用在某些方面比对等指针更安全吗?或者MSVC根本不发出警告应该在哪里?该项目需要维护结构包装,因此我的选择是要么FuncB改为
void FuncB(__unaligned double *x)
{
*x = 0;
}
Run Code Online (Sandbox Code Playgroud)
或者只是FuncA在所有这些情况下使用.后者是更好的,因为它更便携,但我想知道它是否会起作用或者在参考案例中缺少警告只是编译器中的一个缺点.
编辑: 此错误的Microsoft帮助条目在这里.该__unaligned帮助表明,没有理会这一警告会导致异常要在安腾处理器抛出.围绕MSDN的进一步拖网表明,可能存在围绕未对齐引用的问题.虽然这可能不会给我当前的用户带来问题,但如果Itanium架构在未来得到更广泛的使用,我可能会设置一个支持噩梦.Plan现在是为使用压缩结构的所有函数添加特定包装器,以避免使用指针和__unaligned关键字.
引用和指针几乎是一回事(在引擎盖下,可以这么说),所以从安全角度来看,它没有什么不同.它可能更多的是疏忽和/或编译器不太关注引用,因为它们不能在C++环境之外传递(尽管我倾向于认为它只是一种疏忽).
它也可能是编译器更关心指针,因为指针更有可能用于性能,你想要迭代一系列double值(例如,通过分配比结构本身使用更多的空间,并存储更多的double值)之后) - 你不能用参考做到这一点.由于未对齐访问至少比对齐访问慢,这可能会对性能产生影响,并且在某些系统中,它会导致操作系统陷阱,这将"修复"未对齐访问(以几个订单的速度)比普通的对齐访问更慢,或者操作系统简单地说"你的程序导致了一个未对齐的访问,我正在杀死它".
多线程也存在问题,因为未对齐访问可能不会以原子方式更新数据.当然,您应该使用std::atomic或类似于线程之间共享的数据.
x86完全能够double从未对齐的地址读取a .我认为Itanium不是,但我怀疑你无论如何都不使用那个处理器,从统计学上来说.其他较旧的架构,如Alpha可能在读取未对齐的内存时遇到问题.