segmentation fault:段错误
一般有以下原因容易造成段错误:
1)指针:
指针为空"NULL",或者指针未初始化就使用,指针使用完后未释放
2)内存(超出分配的内存空间):
对数组操作不当,数组越界;对字符串操作不当(比如在使用strcpy函数时),字符串空间越界;对动态内存操作不当,内存越界
bus error:总线错误
此类错误目前遇到的情况都是因为内存未对齐造成的,内存对齐问题经常发生在嵌入式中,因为跟平台相关。
内存对齐问题
1)数组(或者数组元素)的数据类型强制转换造成的。
虽然编译时只是警告,没有错误。编译通过了,但是实际运行时,不同类型的变量所占内存大小不同,强制转换就会造成内存对齐问题。
比如以下代码:
int stringtobytearray(char* uuid, uint8_t* uuid_b){
int count;
count=sscanf(uuid,"%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",&uuid_b[0],&uuid_b[1],&uuid_b[2],&uuid_b[3],&uuid_b[4],&uuid_b[5],&uuid_b[6],&uuid_b[7],\
&uuid_b[8],&uuid_b[9],&uuid_b[10],&uuid_b[11],&uuid_b[12],&uuid_b[13],&uuid_b[14],&uuid_b[15]);
return count;
}
分析:%2x期望的数据类型是int类型的,32位,四个字节。所以访问第i个数组元素时,访问的内存地址应该是:(首地址+4*i),或者&array[i*4];但是实际上面代码中,数组类型是uint8_t 类型,只占一个字节。内存地址是按照1字节对齐的。这样就会造成内存对齐问题出现。
解决方案如下
方案1)以四字节的整数倍,访问内存
int stringtobytearray_arm(char* uuid, uint8_t* uuid_b){
int count;
count=sscanf(uuid,"%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",&uuid_b[0],&uuid_b[4],&uuid_b[8],&uuid_b[12],&uuid_b[16],&uuid_b[20],&uuid_b[24],&uuid_b[28],\
&uuid_b[32],&uuid_b[36],&uuid_b[40],&uuid_b[44],&uuid_b[48],&uuid_b[52],&uuid_b[56],&uuid_b[60]);
return count;
}
方案2)保持类型一致,将%2x改成%hhu,%hhu对应的数据类型是一字节的
注意:1)对于标准库中的函数,变量类型,数据结构混合使用一般不会出现bus error错误;但一旦涉及到平台相关的函数,变量,结构体则容易发生内存对齐问题。
2)不要忽略编译过程中编译器发出的警告,这些警告可能对编译不会造成什么影响,但是运行时往往会造成困扰。
3)一定要注意避免平台差异,使代码更通用。