我们经常会发现有两种内存转储(core dump)
一种是段故障(segment fault)通常是在一个非法的地址上进行取值赋值操作造成。
一种是总线错误(bus error)通常是指针强制转换,导致CPU读取数据违反了一定的总线规则。
首先,core就是内存的意思,在半导体应用之前,内存是由铁氧化物圆环制造的(core),但一直沿用至今。
而这两种错误,都是有硬件告知操作系统一个有问题的内存引用。操作系统通过信号,再将错误信息告知进程。缺省情况下,进程收到“总线错误”或“段错误”信号后,将信息转储并终止。当然也可以为这些信号设置一个信号处理程序(signal handler)。
总线错误(bus error),几乎都是有内存未对齐读引起的。内存对齐,就是内存变量的地址只能是其大小的整数倍,这样存储的目的就是为了方便并快速存取内存。一般情况下,编译器都会做好内存对齐工作,为什么又会引发段故障呢?很多情况就是由指针和强制类型转换引起的,如:
union{
char a[10];
int i;
}u;
int *p = (int *)&(u.a[1]);
*p = 17;
当然,还有一些其它原因会引起“总线错误”,如奇偶校验码错误,所引用的内存块不存在。但是现在,内存都有硬件电路检测和修正,一般不会再传到软件层了;除了驱动程序,一般也不会引用不存在的内存块。
段错误,一般是由于引用不位于自己的地址空间的地址引起的。最常见的就是通过一个未初始化,或者有非法值的指针引起的,如:int *p = 0; *p = 7; 而导致指针的非法值可能是由于不同的编程错误引起的,比起“总线错误”更加间接。
段错误一般是由硬件段表转换机构的错误引发,如Sun硬件中的内存管理单元(MMU)。
还有一个微妙之处是,如果未初始化的指针恰好具有未对齐的值,它将产生总线错误,而不是段错误。