在《C专家编程》中提到了总线错误bus error(core dumped)。
总线错误几乎都是由于未对齐的读或写引起的。
它之所以称为总线错误,是因为出现未对齐的内存访问请求时,被堵塞的组件就是地址总线。对齐的意思就是数据项只能存储在地址是数据项大小的整倍数的内存位置上。
现代的计算机架构中,尤其是RISC架构,都需要字对齐,因为与任意的对齐有关的额外逻辑都会使内存系统更大且更慢。
通过迫使每个内存访问局限在一个cache行或者一个单独的页面内,可以极大地简化(并加速)如cache控制器和内存管理单元这样的硬件。
页和cache的大小都是经过精心设计的,这样只要遵守对齐规则就可以保证一个原子数据项不会跨过一个页或cache块的边界。
书中还给出了总线错误的例子:
union { char a[10]; int i; }u; int *p =(int*)&(u.a[1]); *p =17;/*p中未对齐的地址将会引起总线错误,因为数组和int的联合确保了a是按照int的4字节来对齐的,所以“a+1”肯定不是int来对齐的。*/
但是在实际的运行中并没有出现该错误,我的环境是CentOS release 6.2,2.6.32-279.14.1.el6.i686,gcc 4.4.6
后来在网上参考了一个sample程序,将程序修改为如下:
#include <stdlib.h> int main(int argc, char **argv) { #if defined(__GNUC__) # if defined(__i386__) /* Enable Alignment Checking on x86 */ __asm__("pushf\norl $0x40000,(%esp)\npopf"); # elif defined(__x86_64__) /* Enable Alignment Checking on x86_64 */ __asm__("pushf\norl $0x40000,(%rsp)\npopf"); # endif #endif union{ char a[10]; int i; }u; int *p =(int*)&(u.a[1]); *p =17; }
原因是:
x86体系结构会把地址对齐之后,访问两次,然后把第一次的尾巴和第二次的头拼起来。
如果不是x86,那种体系结构下的机器不肯自动干这活,就会产生core。
如果在代码中将对齐检查功能打开,运行后能显示bus error