c# 定位内存快速增长_如何在Linux下检测程序是否存在内存泄漏?

f1af57ed9c3f4a9d4814ef51d630361e.png

C语言是嵌入式开发中永远回避不了的语言,不管是操作系统还是裸机开发,无处不体现着C语言的高效。C语言可以直接操作内存,有着完善的内存管理机制,用好了可以削铁如泥,用不好自断一臂! 不管是C还是C++,很多同学都不可避免犯内存泄漏的错误。因为我们平时写的都是些小程序,就算申请的内存没有释放,也不会影响程序结果,所以很少会关注内存泄漏的问题。但是如果把这个问题放在商用的项目中,就会是一个不小的隐患。 如何判断程序中是否存在内存泄漏,今天就来跟大家分享一个常用工具-- valgrind。 valgrind 堪称Linux内存调试神器,可以用它检测内存泄漏、野指针,或者检查函数调用、缓存、堆栈使用问题。先看下 valgrind 的man手册:
SYNOPSIS          valgrind [valgrind-options] [your-program] [your-program-options]         TOOL SELECTION OPTIONS          The single most important option.       --tool=<toolname> [default: memcheck]              Run the Valgrind tool called toolname, e.g. memcheck, cachegrind, callgrind, helgrind, drd, massif, lackey,              none, exp-sgcheck, exp-bbv, exp-dhat, etc.
它的主要功能都放在【--tool=】选项。
  • memcheck:这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。

  • callgrind:它主要用来检查程序中函数调用过程中出现的问题。

  • cachegrind:它主要用来检查程序中缓存使用出现的问题。

  • helgrind:它主要用来检查多线程程序中出现的竞争问题。

  • massif:它主要用来检查程序中堆栈使用中出现的问题。

  • extension:可以利用core提供的功能,自己编写特定的内存调试工具。

01

未初始化的指针

test1.c

#include int main()  {    int *p;    printf("%d\n", *p);    return 0;  }
编译的时候最好加上【-g】选项,【-g】选项可以在调试的时候看到行号。
gcc test1.c -o test1 -g

通过valgrind调试程序。

cc80759931b181d36e7ede662a4e9c72.png 调试信息清楚的告诉我们,程序第7行存在问题:1、使用了未初始化的指针;2、非法访问指针。导致程序最后出现段错误。

02

内存泄漏

test2.c

#include #include #include int main(){    int *p = (int *)malloc(sizeof(int) * 10);    memset(p, 0, 10);    return 0; }
运行结果:

beaf39631b5d42a657b5e31a0ee18262.png

加上【--leak-check=full】再次运行:

ec5ec71caa21d29b77392b2de0e73121.png

这次运行,明确指出了程序第7行存在内存泄漏,申请了内存,但是最后并没有释放掉。

03

使用野指针

test3.c

#include #include #include int main() {    int *p = (int *)malloc(sizeof(int) * 10);    memset(p, 0, sizeof(int));    free(p);    printf("%d\n", p[0]);    return 0;  }
运行结果:

2b22d56b17e704b610789631a4cb4af4.png

程序中虽然使用了野指针,但是运行并没有出现段错误。这就是C语言内存管理不严格的地方,只有访问了系统保护的内存,才会出现段错误,虽然内存被释放了,但并没有被保护,所以就算访问,也不会出现问题。但是这种不合法的使用还是能被 valgrind 检测出来。

04

堆栈越界访问

test4.c

#include #include int main(){    char *p = (char *)malloc(sizeof(char) * 16);    p[20] = 'x';    free(p);    return 0; }
运行结果:

b213fdfbb30f373a919a91ccb0f3c43d.png

05

重复释放内存

test5.c

#include #include int main(){    char *p = (char *)malloc(sizeof(char) * 1024);    free(p);     free(p);    return 0; }
运行结果:

71ab83d67e60938558c7407dd01d6ae5.png

06

new和delete

valgrind同样适用于C++程序,比如new和delete没有匹配使用、堆栈内存越界访问,用法和上面的一样,这里就不写代码了。

总结

内存泄漏问题在定位问题的时候很难被发现,所以这个时候 valgrind 就可以发挥很大的力量。同时也要提醒大家,平时写代码的时候也要注意,申请了内存用完后一定要释放,就像去图书馆借书一样,光借不还,图书馆迟早要关门。养成良好的编码习惯,毕竟调试程序也很废脑子。

PS.给小伙伴们汇报个事:

《春季智能硬件工程师培训班》

启动报名,限额25位

努力提升硬实力

备战秋招

有需要的小伙伴请提前报名锁定席位?

40f0bcdebd5f5fd1c639041d7eb5a037.png

caa5e91b1e0e845be520fb70648e5d54.png

2271e9b431e71e4ad24025f87bdb11b0.png

db6b6467b6685895f032c2ff4544a192.png

8a9d80fb2fb6e13c540b15ab17f67eea.png

0ea771e2bc21db49bd125bb9b6cf8610.png

45e0a6ac8c927f8ca32c6890e73b4a30.png

148124f216e575c06285980bca150246.png

84c2da2b3809784cab5243643202b9a9.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值