项目经验之谈--栈破坏 -- 案例二

1.前言

前一篇 《项目经验之谈–栈溢出》 已经写到过栈破坏从来导致的程序崩溃问题,这次在项目中又发现此类似BUG。故此再记录下来,谨记下次再犯。

2.项目需求

通过二维码扫描配置camera ID,然后程序就崩溃了。项目需求不是紧要的,这里不多累赘。

3.代码

以下代码为出问题的函数

static void trigger_callback(NV_HANDLE handle, NV_S32 fd, void * pstUserData, NV_S32 status)
{
    stParam param;
    memset(&param, 0, sizeof(param));
    NV_S32 s32Sockfd = 0;
    NV_CHAR strCameraID[86] = {0};
    NV_U8 u8Md5sum[32] = {0};
    NV_CHAR *strDeskey = NULL;
    NV_CHAR *strMd5sum = NULL;
    NV_S32 s32ID = 0;
    NV_CHAR temp[16] = {0};
    NV_U32 u32Size = 0;
    NV_U8 u8Key[8] = {0};
    nv_picture_trigger_snapshot(5);
    if (u32QRcodeFlag != 1)
    {
        NV_ERROR("recognize QRcode failed");
        nv_event_reset_timer(handle, 2000);
    }
    else
    {
        NV_DEBUG("recognize QRcode success");
        //NV_DEBUG("gs_szData: %s", gs_szData);
        memcpy(gs_szCameraID, gs_szData, 16);
        nv_plugin_ctrl_led(NV_LED1_TURN_OFF, nv_plugin_ctrl_callback_release);
        nv_plugin_ctrl_led(NV_LED0_SLOW_FLICKER, nv_plugin_ctrl_callback_release);
        nv_event_unregist(handle);
        NV_DEBUG("unregist handle: %d", handle);
        gs_u32SetWifiFlag = 0;

        generate_key(u8Key);
        strDeskey = netview_dec2hex(u8Key, 8);
        memcpy(gs_szDeskey, strDeskey, 16);
        //NV_DEBUG("gs_szDeskey: %s", gs_szDeskey);

        netview_md5_digest((NV_U8 *)strDeskey, u8Md5sum);
        strMd5sum = netview_dec2hex(u8Md5sum, 16);
        memcpy(gs_szMd5sum, strMd5sum, 32);
        //NV_DEBUG("gs_szMd5sum: %s", gs_szMd5sum);

        get_param(&param);
        //NV_DEBUG("RomVersion: %s", param.RomVersion);
        //NV_DEBUG("ToRomVersion: %s", param.ToRomVersion);
        //NV_DEBUG("u32HasProducedTotalCount: %d", param.u32HasProducedTotalCount);
        gs_s32AppID = param.app_id;
        //NV_DEBUG("app_id: %d", gs_s32AppID);

        if (strlen(param.MacAddr) == 12)
        {
            strcpy(gs_szMacAddr, param.MacAddr);
        }
        else
        {
            strcpy(temp, gs_szCameraID+11);
            s32ID = param.u32HasProducedTotalCount + atoi(temp);
            memset(temp, 0, sizeof(temp));
            sprintf(temp, "%06x", s32ID);
            NV_WARN("temp: %s,s32ID: %d", temp,s32ID);
            sprintf(gs_szMacAddr, "940b2d%s", temp);
        }
        //NV_DEBUG("MacAddr: %s", gs_szMacAddr);

        s32Sockfd = get_acceptscokfd();
        strCameraID[0] = 6;
        strCameraID[1] = param.app_id;
        memcpy(strCameraID+2, "nvttest", 7);
        memcpy(strCameraID+2+7, gs_szCameraID, 16);
        memcpy(strCameraID+2+7+16, strDeskey, 16);
        memcpy(strCameraID+2+7+16+16, strMd5sum, 32);
        memcpy(strCameraID+2+7+16+16+32, param.RomVersion, 10);
        memcpy(strCameraID+2+7+16+16+32+10, param.ToRomVersion, 10);
        u32Size = nv_tcp_send(s32Sockfd, strCameraID, 93);
        NV_WARN("strCameraID : %s",strCameraID);
        if (u32Size != 93)
        {
            NV_DEBUG("u32Size: %d", u32Size);
        }
        else
        {
            nv_create_check_server_ack_timer(1);

        }
    }
}

4.调试

4.1 GDB 调试

一旦出现莫名出现程序闪退或者崩溃,首先就得利用GDB来运行,进行跟踪,跟踪信息:

    Program received signal SIGSEGV, Segmentation fault.
    0xb6ddf9fc in ev_invoke_pending () from /mnt/mtd/firmware/lib/libnvc-event.so
    (gdb) bt
    #0  0xb6ddf9fc in ev_invoke_pending ()
       from /mnt/mtd/firmware/lib/libnvc-event.so
    #1  0xb6de22c8 in ev_run () from /mnt/mtd/firmware/lib/libnvc-event.so
    #2  0xb6de4658 in nv_event_start () at src/netview_event.c:78
    #3  0x0000a7ec in ?? ()
    Cannot access memory at address 0x1
    #4  0x0000a7ec in ?? ()
    Cannot access memory at address 0x1
    Backtrace stopped: previous frame identical to this frame (corrupt stack?)
    (gdb) 

初看,怀疑是libnvc-event.so库中某个函数出现了问题.后来查看libev库,发现也不是这个问题,打印信息容易误导人家,或许我们忽略了最重要的信息

    Cannot access memory at address 0x1
    #4  0x0000a7ec in ?? ()
    Cannot access memory at address 0x1
    Backtrace stopped: previous frame identical to this frame (corrupt stack?)
    (gdb) 

4.2 分析

分析:
corrupt stack :损坏的栈
可以猜测栈被破坏了,nv_event_start函数栈帧的上一级栈帧被破坏了。
由此推断 是 调用nv_event_start函数的上层次函数中出现了问题,该函数栈帧被破坏,数据被改写了。导致该不能够正常返回上一级函数。
而一般损坏栈内存的,一般是内存操作函数,如 memcpystrcpy 等。而且可能存在局部数组。

4.3 问题所在

这里写图片描述

这里写图片描述

I.总结

嵌入式C当中,出现BUG基本上离不开以下几点:

⑴ 程序业务逻辑出错(或算法出错)
   业务逻辑出错或者算法出错,唯一办法就是找出算法错误或解决逻辑问题

⑵ 内存泄漏(堆区管理不当)
   ① 注意编程规范(空间分配,遵循"有借有还")
   ② 建立属于进程自己可管理的内存对象
   ③ 借助例如glibc库来进行定位跟踪(mtrace)

⑶ 越界访问(指针乱入)
   ① 非法指针访问内存(空指针、野指针等)
   ② 栈破坏
   ③ 借助gdb调试工作定位局部问题
   ④ 建立健壮的调试手段(栈回溯)
   ⑤ 借助例如glibc库来进行定位跟踪(backtrace 、backtrace_symbols)

⑷ 系统调用(API)或Libc库等接口使用方式不当(不正确)
   补充理论知识、熟悉接口调用
   善于借助错误接管机制:如 : perror函数,strerror函数,errno

⑸ 第三方库(SDK)本身存在bug.
   慎用第三方库、谨慎选择SDK
  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值