使用valgrind检查内存泄漏(SinoDB)

valgrind是一款被广泛使用的内存泄漏检测工具,可以用来检测程序是否有非法使用内存的问题,例如访问未初始化的内存、访问数组时越界、忘记释放动态内存等问题,本次查漏就使用了这款软件,这类工具市面上有很多,以前也有使用过其他的工具检测,最大的问题就是给了过多的检测信息,没有成功帮忙解决过内存泄漏问题,当然也可能是使用方法不对,总之对此类工具的感觉就是高深却无用。本次在同事的极力安利下尝试了下,改变了我的看法。

下面记录了一次成功检测内存泄漏的过程:

- Valgrind Linux安装

1.  下载,wget ftp://sourceware.org/pub/valgrind/valgrind-3.13.0.tar.bz2

2.   编译安装

 ./configure --prefix=/usr/local/bin

 make;make install

 以上请使用root账号安装。

- valgrind使用

执行valgrind --leak-check=full bin/SqltSnifferService.exe
更深入使用请自行查看帮助选项。

1.测试用例

1018 50 bytes in 2 blocks are definitely lost in loss record 185 of 292
1018 at 0x4A069EE: malloc (vg_replace_malloc.c:270)
1018 by 0x4A06B62: realloc (vg_replace_malloc.c:662)
1018 by 0x43E817: rowdata_header_decode (sqlt_data.c:1924)
1018 by 0x43ABD8: data_row_output (sqlt_data.c:334)
1018 by 0x438B48: data_row_out_handle (sqlt_trace.c:2569)
1018 by 0x435C6B: select_decode (sqlt_trace.c:882)
1018 by 0x436EAF: execute_decode (sqlt_trace.c:1664)
1018 by 0x437199: exesql_decode (sqlt_trace.c:1721)
1018 by 0x4350A4: tt_decode (sqlt_trace.c:587)
1018 by 0x434C02: sqlt_trace_run (sqlt_trace.c:415)
1018 by 0x404194: DeSqltStream (pds-sqlt.c:398)
1018 by 0x444719: CsTcpFlushAck (cstcp.c:1284)
1018
1018 422 bytes in 2 blocks are definitely lost in loss record 219 of 292
1018 at 0x4A069EE: malloc (vg_replace_malloc.c:270)
1018 by 0x43EB1A: code_set_conv (sqlt_data.c:2050)
1018 by 0x436CE3: execute_decode (sqlt_trace.c:1621)
1018 by 0x437199: exesql_decode (sqlt_trace.c:1721)
1018 by 0x4350A4: tt_decode (sqlt_trace.c:587)
1018 by 0x434C02: sqlt_trace_run (sqlt_trace.c:415)
1018 by 0x404194: DeSqltStream (pds-sqlt.c:398)
1018 by 0x444719: CsTcpFlushAck (cstcp.c:1284)
1018 by 0x44257A: CsTcpStream (cstcp.c:561)
1018 by 0x442DAC: CsTcpHandler (cstcp.c:742)
1018 by 0x441422: CsPcapPacketHandler (cspcap.c:496)
1018 by 0x4E7015D: pcap_offline_read (savefile.c:380)

输出信息显示有两处地方存在内存泄漏,并且给出了调用关系,仔细核查后,发现代码的确存在问题。

done:
    if(!rowdata_head.null_col_arr && rowdata_head.arr_size >0) {
        free(rowdata_head.null_col_arr);
        rowdata_head.null_col_arr = NULL;
        rowdata_head.arr_size = 0;
        rowdata_head.null_col_num = 0;
    }

应该要将条件改成if(rowdata_head.null_col_arr && rowdata_head.arr_size >0)

if (sql_cmd_find(&st->sql_info, &sql_cmd->sql_id, &sql_cmd)) {
  /*sql_cmd be push*/
  sql_cmd = NULL;
  sql_str = NULL;           
}

结合上下文,此处的sql_str不能设置为NULL。

2.测试用例

31636 Invalid read of size 1
31636 at 0x43ECC3: sqlt_u16_read (sqlt_msg.c:65)
31636 by 0x43AB9A: data_row_output (sqlt_data.c:323)
31636 by 0x438B46: data_row_out_handle (sqlt_trace.c:2577)
31636 by 0x4387AB: bind_decode_091d (sqlt_trace.c:2359)
31636 by 0x4381BC: bind_decode (sqlt_trace.c:2183)
31636 by 0x436DB4: execute_decode (sqlt_trace.c:1636)
31636 by 0x437197: exesql_decode (sqlt_trace.c:1729)
31636 by 0x4350A4: tt_decode (sqlt_trace.c:587)
31636 by 0x434C02: sqlt_trace_run (sqlt_trace.c:415)
31636 by 0x404194: DeSqltStream (pds-sqlt.c:398)
31636 by 0x444729: CsTcpFlushAck (cstcp.c:1284)
31636 by 0x44258A: CsTcpStream (cstcp.c:561)
31636 Address 0x68b4c74 is 0 bytes after a block of size 1,620 alloc'd
31636 at 0x4A06BE0: realloc (vg_replace_malloc.c:662)
31636 by 0x43A0FD: tt_packet_push (tt_packet.c:190)
31636 by 0x434B4E: sqlt_trace_run (sqlt_trace.c:376)
31636 by 0x404194: DeSqltStream (pds-sqlt.c:398)
31636 by 0x444729: CsTcpFlushAck (cstcp.c:1284)
31636 by 0x44258A: CsTcpStream (cstcp.c:561)
31636 by 0x442DBC: CsTcpHandler (cstcp.c:742)
31636 by 0x441432: CsPcapPacketHandler (cspcap.c:496)
31636 by 0x4E7015D: pcap_offline_read (savefile.c:380)
31636 by 0x4E62B8F: pcap_loop (pcap.c:427)
31636 by 0x441629: CsPcapLoop (cspcap.c:587)
31636 by 0x42EEB3: ProjectLoop (pds-framework.c:406)
31636

此处信息显示读取了无效的数据,问题代码如下。

if(sqlt_u16_read(msg) != 0x0c0d) {
       break;
}  

msg只剩下一个byte,而sqlt_u16_read(msg)是读取2个byte,这可能也会造成越界读取错误,甚至程序crash。

代码修改为

if(msg_len >1 && sqlt_u16_read(msg) != 0x0c0d) {
       break;
}  

以上代码修改编译后,重新运行,现在的信息如下 。

31636 LEAK SUMMARY:
31636 definitely lost: 0 bytes in 0 blocks
31636 indirectly lost: 0 bytes in 0 blocks
31636 possibly lost: 0 bytes in 0 blocks
31636 still reachable: 1,840,003 bytes in 15,234 blocks
31636 suppressed: 0 bytes in 0 blocks
31636 Reachable blocks (those to which a pointer was found) are not shown.
31636 To see them, rerun with: --leak-check=full --show-reachable=yes

现在没有错误提醒了。

通过以上介绍可以看出这款软件的强大,第一次使用时,并没有发现特别有用的信息。可能的原因是测试用例的问题,需要将程序编译成debug版,即需要开启-g编译选项。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值