一、导致SIGSEGV
1.试图对只读映射区域进行写操作 。
2.访问的内存已经被释放,也就是已经不存在或者越界。
3.官方说法是:
SIGSEGV --- Segment Fault. The possible cases of your encountering this error are:
(1)buffer overflow --- usually caused by a pointer reference
out of range.
(2)stack overflow --- please keep in mind that the default stack size is 8192K.
(3)illegal file access --- file operations are forbidden on our judge system.
二、导致SIGBUS信号:
1.硬件故障,不用说,程序员最常碰上的肯定不是这种情形。
2.Linux平台上执行malloc(),如果没有足够的RAM,Linux不是让malloc()失败返回, 而是向当前进程分发SIGBUS信号。
注: 对该点执怀疑态度,有机会可自行测试确认当前系统反应。
3.某些架构上访问数据时有对齐的要求,比如只能从4字节边界上读取一个4字节的 数据类型。IA-32架构没有硬性要求对齐,尽管未对齐的访问降低执行效率。另外一些架构,比如SPARC、m68k,要求对齐访问,否则向当前进程分发SIGBUS信号。
4.试图访问一块无文件内容对应的内存区域,比如超过文件尾的内存区域,或者以前有文件内容对应,现在为另一进程截断过的内存区域。
数据对齐导致的SIGBUS:
同样的代码,在vs下运行正常,在android ndk下却崩溃:
signal 7(SIGBUS),code 1 (BUS_ADRALN),fault addr 0xe6b82793
Func(short *pVY[])
{
short *dstY[2] = {pVY[0],pVY[1]};//使用backtrace定位,crash在这一句
}
pVY[0],pVY[1]是从一个统一分配的buffer偏移得来的。
1.考虑内存对齐的原因
pVY[0],pVY[1]:0xee25ffe0,0xee262470 。都是32字节对齐的。
重新分配按64字节对齐,pVY[0],pVY[1]:0xee260600,0xee262b00 ,实际已经256字节对齐了,错误同样出现.
不是pVY[0]和[1]内存没对齐的原因
it appears that SIGBUS 7 is a data misalignment issue, and SIGSEGV 11 is a write to inaccessible memory.
打印出pVY的值为0xe6b82793,正好与fault addr一样,pVY + 1的值为0xe6b82797.
参考:http://stackoverflow.com/questions/13077791/fatal-signal-7-sigbus-at-0x00000000-code-2
Linux操作系统会对于 非对齐内存访问的进程,发送SIGBUS的信号,你的程序,接收到这个信号后,进行coredump,并退出了。
Windows操作系统允许 非地址对齐的内存访问(会损失性能),所以程序在Windows操作系统下,不会出现error。
Win32平台下的微软VC编译器在默认情况下采用如下的对齐规则: 任何基本数据类型T的对齐模数就是T的大小,即sizeof(T)。比如对于double类型(8字节),就要求该类型数据的地址总是8的倍数,而char类型数据(1字节)则可以从任何一个地址开始。Linux下的GCC奉行的是另外一套规则:任何2字节大小(包括单字节吗?)的数据类型(比如short)的对齐模数是2,而其它所有超过2字节的数据类型(比如long,double)都以4为对齐模数。
应该是对pVY,pVY+1的非对齐内存访问造成的,pVY(0xe6b82793)存的是(short*) pVY[0]。
pVY来自class的成员变量:
class A{
...
short *pVY[6];
};
在vs下调试,pVY 为0x001cd9a8,是8字节对齐的。
在ndk下, pVY+0到5为:0xe6b82793,797,79b,79f,7a3,7a7,默认并没有对齐。
解决办法:
1.不进行赋值,函数体内直接使用形参操作:
Func(short *dstY[])
{
for(x = 0;x<w;x++){
dstY[0][x] = x;
dstY[1][x] = x;
}
}
2.设置内存对齐
#pragma pack(push) //保存对齐状态
#pragma pack(8)//设定为4字节对齐
class A{
...
short *pVY[6];
};
#pragma pack(pop)
在ndk下pVY的值为0xe6b82794