WinCE平台下如何通过系统异常信息定位程序bug位置

 2014-10-28         

  在程序开发时,时常会遇到异常报错的情况。有时因为环境因素,通过调试工具很难在调试时复现故障情况,或者很难在短时间内复现故障情况。随着工程代码量的增加,定位程序出错位置变得更加困难。

 

  在使用基于WINCE平台的英创系列工控主板进行应用程序开发时,当程序产生异常退出,CE操作系统将通过调试串口打印类似如下错误信息。根据这些信息,结合应用程序对应的map文件,就能够快速定位程序异常的位置,本文将详细介绍这一方法。

 

  

 

准备工作

 

  以一个简单的控制台程序test_exception.exe为例,模拟会产生异常的程序,代码如下。

 

  #include 'stdafx.h' 
  #include 'windows.h'
  #include 'commctrl.h'

  void testErr(char* pbuf, int len)
  {
    *(pbuf+len) = len;
    return;
  }

  int _tmain(int argc, _TCHAR* argv[])
  {
    int i;
    char* p = 0;
    char buf[10];
    for (i=0; i< 10;i++)
    {
      printf('i=%d\n',i);
      testErr(buf, i);
      Sleep(1000);
    }
    printf('test err\n');
    Sleep(1000);
    testErr(p, 10);
    for (;;)
    {
      printf('.');
      Sleep(1000);
    }
    return 0;
  }

 

  这段代码有个非常明显的致命错误,char* p = 0;实际上是定义的是p的地址为0,之后testErr(p, 10);函数对p地址的操作会造成指针越界,程序将产生异常结束。

 

设置工程属性

 

  首先需要设置工程属性,让工程编译时产生MAP文件。

 

  

 

  另外还可以选择添加汇编输出信息。

 

  

 

  这样我们在重新编译程序后,就可以在编译目录里找到源文件的.map和.cod两种调试辅助文件。

 

记录DEBUG信息

 

  连接英创主板的调试串口至PC主机的串口,打开串口工具(英创主板默认的调试串口参数为115200,8-N-1),以监听DEBUG口打印信息。

 

  运行test_exception程序,记录DEBUG口打印的异常信息。

 

  

 

  主要记录出错的exe(或者dll)名test_exception.exe,PC地址00011024,和RA地址000110bc。

 

查看map文件

 

  查找PC地址00011024,和RA地址000110bc附近的信息。

 

  

 

  对照PC地址能够知道,testErr函数的地址00011000,这个函数地址偏移00011024-00011000的地方出错了。

 

  对照RA地址能够知道,最后一次调用该函数未出错时的位置,在wmain函数地址偏移000110bc -00011034的地方。

 

  这样,我们不但知道了是哪个函数出的错,也知道了在哪里调用出的错。

 

查看cod文件

 

  为了进一步确定范围,打开编译目录下对应的cod文件test_exception.cod。

 

  

 

  查看testErr函数信息,可以知道,在偏移地址00011024-00011000=00024的地方的汇编,以及出错的C代码,为test_exception.cpp第10行的*(pbuf+len) = len;

 

  

 

  查看wmain函数信息,可以知道,返回地址000110bc -00011034=00088,最后一次正常调用testErr的地方是在test_exception.cpp第22行。

 

定位错误

 

  这样稍加分析,我们就可以确定出错位置了。

 

  

 

  最后,可以在代码附近添加打印或日志log记录,来验证异常位置判断是否正确。

 

  需要例程可以联系英创工程师。

 

  如果产生异常提示信息的不是用户程序,而是'coredll.dll',则判定为是驱动出错,请联系英创工程师检查出错原因。