野指针追踪

来源:互联网 发布:淘宝联盟购买省钱在哪 编辑:程序博客网 时间:2024/05/20 18:42

一、    简介

C语言里面最强大的莫过于指针了。它创造了程序思想的无限可能。但同时指针用过头就像脱缰的野马,让程序员死的心都有。

指针即指向一个地址的变量。当指向这个地址的变量是非法的,那这个指针就变成野指针了。而野指针是很难找出问题的,特别是一些很隐蔽性的野指针往往程序要运行数天才会出故障。

Cortex-M3当指针用法错误时,例如指针指向一个只读区域,但对该区域进行写操作,会产生BusFaultException的异常,如果我们利用好这个异常就会比较容易的找到出错的代码位置。再通过寄存器的上下文就比较容易判断出野指针产生的原因。

二、    Cortex-M3 中断

Cortex-M3中断时依次把xPSR, PC, LR, R12以及R3-R0由硬件自动压入适当的堆栈中:如果当响应异常时,当前的代码正在使用PSP,则压入PSP,也就是使用进程堆栈;否则就压入MSP,使用主堆栈。

而这些入栈的寄存器就是野指针出事的事故现场。特别是LR寄存器就是野指针程序执行错误的内存地址。

通过获取SP的地址,然后逆向查找内存数据,就能找到事故发生的地方。

三、    举例

使用一个定时器,他的数据结构包含

typedef struct __TMR{

INT8U tmrEn;

。。。
    }TMR ;

定义一个野指针:

TMR *tmr = 0;

产生异常:

tmr->tmrEn = 1;

我们来看一下Keil MDK调试的实际界面:

其中BusFaultException()就是野指针事故后进入的异常。我们可以看到当前SP指针指向:0x20001760的地址,而图中1所示的内存内容和左侧的1表示的当前寄存器值是一致的。依次是R0,R1,R2,R3,R12。

从2的内存中可以看书,事故现场在0x0800614F位置,我们可以看到tmr->TmrEn = 1代码是在0x0800614E处。相差一是Cortex-M3运行在thumb2模式下的原因。可以看出只要能够读到LR的值就可以找到事故地址。

可以看到入栈的PC指针为0x8006158和LR还是有区别的,这是Cortex-M3响应中断最小有6个周期的延迟的原因。

四、    BusFaultException实现举例

示例中只打印出了LR和PC的值,异常时获取MSP的值,然后通过入栈顺序,通过偏移量找到LR和PC,然后用上一篇中提到的lcd_debug程序打印出这两个值。

原创粉丝点击