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应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况。它能检测以下问题:
- 对未初始化内存的使用;
- 读/写释放后的内存块;
- 读/写超出malloc分配的内存块;
- 读/写不适当的栈中内存块;
- 内存泄漏,指向一块内存的指针永远丢失;
- 不正确的malloc/free或new/delete匹配;
- memcpy()相关函数中的dst和src指针重叠
堆内存泄露报告
- 堆内存使用情况概述(HEAP SUMMARY)
- 确信的内存泄露报告(definitely lost)
- 可疑内存操作报告 (show-reachable=no关闭,打开:–show-reachable=yes)
- 泄露情况概述(LEAK SUMMARY)
日志报告格式
{问题描述}
at {地址、函数名、模块或代码行}
by {地址、函数名、代码行}
by …{逐层依次显示调用堆栈}
Address 0x??? {描述地址的相对关系}
memcheck包含的错误
-
非法读写错误 :比如读写还没有分配的内存块、读写已经被free的内存块、内存访问越界
提示信息:[invalid read of size 4]
-
使用未初始化的内存,使用了未定义的值,有两种未初始化的原因:函数中的局部变量没有被初始化;堆上的内存块在使用之前没有被初始化。
提示信息:[Conditional jump or move depends on uninitialised value]
-
系统调用中参数未已经初始化,程序提供的buffer不可用
提示信息:[syscall param write(buf) points to uninitilaised bytes]
-
非法释放:重复释放内存块,或者指针没有指向内存的起始位置。
提示信息:[invalid free()]
-
使用不适当的释放函数释放:
- 如果与分配 malloc, calloc, realloc, valloc或者 memalign,必须使用free。
- 如果分配new,必须使用delete。
- 如果分配new[],必须使用delete[]。
提示信息:[Mismatched free()/delete/delete[]]
-
内存块重叠,比如使用 memcpy 函数时源地址和目标地址发生重叠。
提示信息:[source and destination overlap in memcpy(,)]
-
Fishy argument values:需要的内存大小是负数或者大的离谱的正数。
提示信息:[Argument 'size' of function malloc has a fishy (possibly negative) value: -3]
-
内存泄漏:
-
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,一定要调用相应的函数释放