valgrind使用场景
检查代码中在堆上分配存储器,但是没释放的位置,也就是找出存储器泄露位置
valgrind工作原理
通过伪造malloc可以监控分配在堆上的数据,当程序想分配堆存储器时,valgrind将会拦截你对malloc和free的调用,然后运行自己的malloc和free函数,它会记录哪段代码分配了哪段存储器,结束的时候,valgrind会汇报堆上有哪些数据,并告诉你这些数据由哪段代码创建
安装valgrind
curl -O http://valgrind.org/downloads/valgrind-3.11.0.tar.bz2
tar -xjvf valgrind-3.11.0.tar.bz2
cd valgrind-3.11.0
./configure && make && make install
valgrind --version
使用valgrind
gcc -g test.c -o test (其中-g是告诉编译器要记录需编译代码的行号)
valgrind --leak-check=full ./test
例子
createByMalloc.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//结构定义函数体的外面多个函数才能共享
typedef struct island {
char *name;
char *open;
char *close;
struct island *next;
} island;
void display(island *start);
island* create(char *name);
int main()
{
char name[80];
fgets(name, 80, stdin);
island *i = create(name);
fgets(name, 80, stdin);
island *i1 = create(name);
i->next = i1;
display(i);
release(i);
}
island* create (char *name)
{
island *i = malloc(sizeof(island));
//注意在此处一定用用strdup在堆上存储,如果都是在栈上存储,函数结束后会释放内存空间,每次都只能保存最后传入的name指针指向的值
i->name = strdup(name);
i->open = "09:00";
i->close = "17:00";
i->next = NULL;
return i;
}
void display(island *start) {
island *i = start;
for (;i!=NULL;i=i->next) {
printf("name:%s,open:%s-%s\n",i->name, i->open, i->close);
}
}
gcc -g createByMalloc.c -o createByMalloc
valgrind --leak-check=full ./createByMalloc
1.total heap usage: 520 allocs, 100 frees, 49,567 bytes allocated
表示520次存储器,100次被释放
2.at 0x100007EA1: malloc (vg_replace_malloc.c:303)
by 0x100000D7A: create (createByMalloc.c:33)
by 0x100000CED: main (createByMalloc.c:23)
明确指出了可能出问题的行,查看代码可以发现是create的33行分配的堆上的存储器没有被释放,所以加上释放代码就好了
正确例子:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//结构定义函数体的外面多个函数才能共享
typedef struct island {
char *name;
char *open;
char *close;
struct island *next;
} island;
void display(island *start);
void release1(island *start);
void release(island *start);
island* create(char *name);
int main()
{
char name[80];
fgets(name, 80, stdin);
island *i = create(name);
fgets(name, 80, stdin);
island *i1 = create(name);
i->next = i1;
display(i);
}
island* create (char *name)
{
island *i = malloc(sizeof(island));
//注意在此处一定用用strdup在堆上存储,如果都是在栈上存储,函数结束后会释放内存空间,每次都只能保存最后传入的name指针指向的值
i->name = strdup(name);
i->open = "09:00";
i->close = "17:00";
i->next = NULL;
return i;
}
void display(island *start) {
island *i = start;
for (;i!=NULL;i=i->next) {
printf("name:%s,open:%s-%s\n",i->name, i->open, i->close);
}
}
void release1(island *start) {
island *i = NULL;
for(i=start;i!=NULL;i=i->next) {
free(i->name);
free(i);
}
}
void release(island *start) {
island *i = start;
island *next = NULL;
for(;i!=NULL;i=next) {
next = i->next;
free(i->name);
free(i);
}
}