绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
使用valgrind检查内存泄漏(SinoDB)
2022-05-06 15:05:37

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编译选项。

分享好友

分享这个小栈给你的朋友们,一起进步吧。

专业的官方救援小分队
创建时间:2019-11-07 09:33:49
我是一个官方吐槽小栈我们是技术栈的搬砖IT民工。 我知道你们在使用小栈的过程中会遇到很多问题: 迭代功能太鸡肋? 界面太low? 编辑器难用到爆? ··· 需求尽管提,槽点尽管说,技术救援小分队在线为您灭火,致力于提供专业的解答,提供迅疾的反馈。 悄悄的说,毛线不懂的运营喵、产品狗他们不在,我们一起吐槽!
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

栈主、嘉宾

查看更多
  • 山中老狐狸
    栈主
  • 栈栈
    嘉宾
  • gaokeke123
    嘉宾
  • Ys
    嘉宾

小栈成员

查看更多
  • gyu
  • aabbcc1832611
  • 飘絮絮絮丶
  • h313895741
戳我,来吐槽~