valgrind检查内存泄漏

引入

在使用sqlite3插入数据时,我使用了sqlite3_mprintf()把语句放到sql中,但是后面发现会导致内存泄漏

int insert_database(void *pack, int size)
{
	int    rc = 0;
	char   *sql;

	sql = sqlite3_mprintf("INSERT INTO Temp (packet) VALUES (?)");
	
    return rc;
}

sqlite_mprintf()函数

sqlite3_mprintf()的作用是将结果写入到sqlite3_malloc()获取的内存中,例程返回的字符串应该使用sqlite3_free()进行释放,如果无法申请到足够的内存,则会返回NULL指针。

使用valgrind检查内存泄露

下载安装

下载地址: https://www.valgrind.org/downloads/

安装:

tar -xjf valgrind-3.22.0.tar.bz2

cd valgrind-3.22.0/

./configure --prefix=`pwd`/../install  //可以--help查看配置项

make

make install

使用

valgrind --help 可查看使用方法和选项

Memcheck工具

功能

这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况。它能检测以下问题:

  1. 对未初始化内存的使用;
  2. 读/写释放后的内存块;
  3. 读/写超出malloc分配的内存块;
  4. 读/写不适当的栈中内存块;
  5. 内存泄漏,指向一块内存的指针永远丢失;
  6. 不正确的malloc/free或new/delete匹配;
  7. memcpy()相关函数中的dst和src指针重叠

堆内存泄露报告

  • 堆内存使用情况概述(HEAP SUMMARY)
  • 确信的内存泄露报告(definitely lost)
  • 可疑内存操作报告 (show-reachable=no关闭,打开:–show-reachable=yes)
  • 泄露情况概述(LEAK SUMMARY)

日志报告格式

{问题描述}
at {地址、函数名、模块或代码行}
by {地址、函数名、代码行}
by …{逐层依次显示调用堆栈}
Address 0x??? {描述地址的相对关系}

memcheck包含的错误

  1. 非法读写错误 :比如读写还没有分配的内存块、读写已经被free的内存块、内存访问越界

    提示信息:[invalid read of size 4]

  2. 使用未初始化的内存,使用了未定义的值,有两种未初始化的原因:函数中的局部变量没有被初始化;堆上的内存块在使用之前没有被初始化。

    提示信息:[Conditional jump or move depends on uninitialised value]

  3. 系统调用中参数未已经初始化,程序提供的buffer不可用

    提示信息:[syscall param write(buf) points to uninitilaised bytes]

  4. 非法释放:重复释放内存块,或者指针没有指向内存的起始位置。

    提示信息:[invalid free()]

  5. 使用不适当的释放函数释放:

    • 如果与分配 malloc, calloc, realloc, valloc或者 memalign,必须使用free。
    • 如果分配new,必须使用delete。
    • 如果分配new[],必须使用delete[]。

    提示信息:[Mismatched free()/delete/delete[]]

  6. 内存块重叠,比如使用 memcpy 函数时源地址和目标地址发生重叠。

    提示信息:[source and destination overlap in memcpy(,)]

  7. Fishy argument values:需要的内存大小是负数或者大的离谱的正数。

    提示信息:[Argument 'size' of function malloc has a fishy (possibly negative) value: -3]

  8. 内存泄漏:

    • still reachable:内存指针还在还有机会使用或释放,指针指向的动态内存还没有被释放就退出了

    • definitely lost:确定的内存泄露,已经不能访问这块内存

    • indirectly lost:指向该内存的指针都位于内存泄露处

    • possibly lost:可能的内存泄露,仍然存在某个指针能够快速访问某块内存,但该指针指向的已经不是内存首位置

实例

 #-g:让 memcheck 工具可以取到出错的具体行号
 gcc -g socket_client.c -o socket_client 
#使用memcheck工具对socket_client程序进行包含内存泄漏的检查,并将日志保存到check.log
valgrind --tool=memcheck --leak-check=yes --log-file=check.log ./socket_client

修改后:

由此可见,即使我们自己没有使用malloc()申请内存,在调用一些开源库的时候,函数内部也可能会存在malloc,一定要调用相应的函数释放

posted @ 2024-04-10 19:47  梨子Li  阅读(164)  评论(0编辑  收藏  举报