【发布时间】:2010-12-25 22:34:54
【问题描述】:
我想了解为什么我收到此代码的总线错误。
int main()
{
int p=34;
int *pp= (int *) ((char *)&p+1);
cout<<*pp<<"\n";
return 0;
}
【问题讨论】:
-
除了对齐问题,这是未定义的行为。你读书越界了。因此,该程序可能会以更具想象力的方式爆发。
我想了解为什么我收到此代码的总线错误。
int main()
{
int p=34;
int *pp= (int *) ((char *)&p+1);
cout<<*pp<<"\n";
return 0;
}
【问题讨论】:
这无疑是一个对齐问题。在许多架构中,某些类型必须正确对齐,例如 4 字节整数必须以 4 字节边界开始。
如果您访问未对齐的数据,一些架构不会在意,其他架构会运行得更慢,还有一些架构(例如在本例中)会陷入困境。
当您创建整数 p 时,它将在堆栈上正确对齐的地址是正确的倍数。
通过将该地址向上移动一个字节,并将其取消引用为int,您将导致SIGBUS。
This link at Oracle 显示对齐要求。简而言之:
【讨论】:
16 位数量必须以 16 位或 2 字节对齐方式存储,并且 32 位(4 字节)的地址必须是 4 的倍数。
许多 CPU 支持非对齐访问,但它需要芯片中的额外电路,以及额外的执行时间来运行额外的内存总线周期来获取奇数字节。这是一种特别常见的 RISC 处理器理念,即要求编译器和程序员更加小心谨慎地布置数据以提高速度和简化电路,这是可以接受的权衡。
顺便说一句,像这样的低地址不太可能在有效内存中。但是您的示例确实说明了对齐异常优先于 SEGFAULT 异常。
【讨论】: