前言
项目代码中经常出现莫名其妙的Bus error问题,并且代码中增加很多try catch 后依然不能将错误捕获,一旦Bus erro出现,进程直接崩溃掉。类似如下这种:
经查询google,出现该问题一般是因为地址未对齐引起的,也就是程序试图访问一个不是地址的值。从而导致该错误。后经公司高工通过gdb运行代码后查看汇编发现,寄存器中确实存储了一个非地址的值(50位, 64位机器的实际内存地址应该为48位,高位用于寻址),导致在访问时出现Bus-error。
更奇怪的是,该问题不会一直复现,而是经常跑几个小时,然后在调用函数指针的时候崩溃一次。提示UpdateDataPtr指向的一个空地址。
对于此,高工的判断要么是数组越界,要么是因为野指针导致该函数指针被意外修改。
顺着这个思路,一开始是通过内存监控,查看是谁修改了该内存,但是并未守到结果。此时高工想通过分析内存的方式看能不能找到一些线索。
操作方法就是在该指针前后增加标记变量,然后通过程序挂掉时候的core dump 查看那时刻的内存结构,从而尝试分析问题
最后发现代码中的一个单例中定义了一个数组u_char crcbuf[64]; 在写这个数据的时候发生越界,最终将该变量下的指针变量也覆盖了
写成我们接收到的里程计数据了,从此真相大白!
对于此,接着分析是如何导致该问题的呢?
看看报文就知道了,正常报文的数据部分出现了报头一样的情况,导致程序误认为读取的数据大小为176个字节,那么在计算crcbuf的时候也会尝试放入176个字节,最终产生数组越界,将函数指针覆盖。
总结
1 该问题从出现到解决持续了好几周,一直没有好的方案。
2 遇到问题不能回避,应该迎难而上,实在不行请教公司高工。
3 C++ 中无法对数组越界的问题进行捕获, 因此务必小心使用数组和指针
4 C++中内存分析和gdb调试要及早掌握,对于分析复杂问题帮助很大