一、leetcode报错之:member access within misaligned address
在leetcode上做一个道题,报错如下:
Line 70: Char 15: runtime error: member access within misaligned address 0xbebebebebebebebe for type 'struct ListNode', which requires 8 byte alignment (ListNode.c)
0xbebebebebebebebe: note: pointer points here
<memory cannot be printed>
检查了代码,并且拷贝到自己机器上运行,都是OK的。
后来上网查了一下,原来是因为链表节点中有指针,申请空间后,这个指针没有赋值为NULL导致访问时next域的值还是垃圾数据,导致访问内存出错。
struct ListNode {
int val;
struct ListNode *next;
};
解决办法:
1. malloc后,对指针进行赋值操作。
2. 时用calloc接口,直接清空分配的空间。
二、 头文件有引发的错误。
问题现象:在项目中引用了一个第三方的动态库,使用了里面的API接口。编译通过。在运行时出现段错误,通过gdb查看函数调用栈,显示死在libc里面,无可见符号。
仔细检查代码,发现所有调用过程都正确,参数也正确。最后通过和demo的代码比对,发现没有没有包含头文件,而所使用的函数是有返回值的。添加头文件后,就可以正常运行了。
然后回过头来仔细研究此问题。首先想到反汇编,看看有无头文件生成的汇编代码到底有何区别。
通过对比发现,没有头文件时,汇编代码中多了一条指令:
sxtw x0, w0
这条指令的意思是将w0寄存器的值扩展到64位,再赋值给x0寄存器。
gdb断点调试两个可执行程序:
发现再出现异常时,函数返回值被扩展到64位(使用的系统是64位系统)前32位全部被填充1.
其中出错的原因很可能是这样的,没有头文件声明,编译器默认的返回值是4字节的int,而在64位系统中,函数返回值保存在64位寄存器中,所以使用了sxtw指令进行了扩展。所以最后承接返回值的变量拿到的值就是错误的,如截图中的地址,导致访问出错。(详细原因有待继续核实)
其实这个问题很好避免的,就是关注编译过程中的警告信息,消除警告,可以避免很多奇奇怪怪的问题,毕竟编译器亲自出马指出了可能的坑。所以,要养成一个良好的编程习惯。
参考:
https://blog.csdn.net/imred/article/details/50756016?locationNum=10&fps=1