源代码
//导入printf函数,用于输出#include <stdio.h>//导入assert函数,断言,用于获取内存是否异常#include <assert.h>//导入malloc函数,用于内存分配, Allocate SIZE bytes of memory#include <stdlib.h>//导入strdup函数,用于字符串的复制#include <string.h>struct Person {char *name;int age;int height;int weight;};//从方法的声明上可以看出,该方法的返回值是一个struct Person*,指向Person结构体的指针struct Person* Person_create(char *name, int age, int height, int weight){//申请指定长度的内存//sizeof获取的长度是 8 + 4 + 4 + 4 = 20个字节//name*是一个地址,长度是8个字节,也就是64位的地址//每个int占用4个字节struct Person *who = malloc(sizeof(struct Person));//判断malloc返回是否成功,成功的话,who指针不为空,肯定会指向一个内存块的首地址//NULL是一个特殊常量,表示“unset or invalid pointer"assert(who != NULL);//使用->语法为结构体赋值//strdup其实和malloc差不多,都是分配一段内存,不过区别是strdup另外还需要将字符串复制到新内存空间中//strdup在此处的目的是该struct真正的用于该字符串,而不是其他地方也引用,防止被其他地方修改或者释放who->name = strdup(name);who->age = age;who->height = height;who->weight = weight;return who;}//良好编程习惯:有create的地方,肯定会有释放的地方void Person_destroy(struct Person *who){//良好编程习惯:在释放前,同样要判断指针是否合法assert(who != NULL);//释放字符串和Person对象占用的内容空间//如果不释放的话,会造成内存泄漏//free(who->name);free(who);}void Person_print(struct Person *who){printf("Joe-inner function is at memory location %p: \n", &who);//结构体成员,使用->来访问printf("Name: %s\n", who->name);printf("\tAge: %d\n", who->age);printf("\tHeight: %d\n", who->height);printf("\tWeight: %d\n", who->weight);}int main(int argc, char *argv[]){// make two people structuresstruct Person *joe = Person_create("Joe Alex", 32, 64, 140);struct Person *frank = Person_create("Frank Blank", 20, 72, 180);// print them out and where they are in memoryprintf("Joe is at memory location %p: \n", joe);printf("Joe is at memory location %p: \n", &joe);Person_print(joe);printf("Frank is at memory location %p: \n", frank);Person_print(frank);// make everyone agr 20 years and print them againjoe->age +=20;joe->height -=2;joe->weight +=40;Person_print(joe);frank->age +=20;frank->height +=20;Person_print(frank);// destroy them both so we clean upPerson_destroy(joe);Person_destroy(frank);return 0;}
安装valgrind
apt update apt install valgrind
编译程序,并使用valgrind执行
valgrind --leak-check=full ./ex16
输出结果如下:
==11300==
==11300== HEAP SUMMARY:
==11300== in use at exit: 21 bytes in 2 blocks
==11300== total heap usage: 5 allocs, 3 frees, 1,093 bytes allocated
==11300==
==11300== 9 bytes in 1 blocks are definitely lost in loss record 1 of 2
==11300== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11300== by 0x4EDBAF9: strdup (strdup.c:42)
==11300== by 0x10882E: Person_create (ex16.c:33)
==11300== by 0x108966: main (ex16.c:66)
==11300==
==11300== 12 bytes in 1 blocks are definitely lost in loss record 2 of 2
==11300== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11300== by 0x4EDBAF9: strdup (strdup.c:42)
==11300== by 0x10882E: Person_create (ex16.c:33)
==11300== by 0x108985: main (ex16.c:67)
==11300==
==11300== LEAK SUMMARY:
==11300== definitely lost: 21 bytes in 2 blocks
==11300== indirectly lost: 0 bytes in 0 blocks
==11300== possibly lost: 0 bytes in 0 blocks
==11300== still reachable: 0 bytes in 0 blocks
==11300== suppressed: 0 bytes in 0 blocks
==11300==
==11300== For counts of detected and suppressed errors, rerun with: -v
==11300== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
分析
从下面可以看出:
total heap usage: 5 allocs, 3 frees, 1,093 bytes allocated
分配了5次内存,但是只释放3次。
说明有两次没有释放。
==11300== 9 bytes in 1 blocks are definitely lost in loss record 1 of 2 ==11300== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11300== by 0x4EDBAF9: strdup (strdup.c:42)
==11300== by 0x10882E: Person_create (ex16.c:33)
==11300== by 0x108966: main (ex16.c:66)
此处泄漏了9个字节,是由strdup申请未释放的。
再综合代码,就可以找到未释放的位置,如下:
