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调试程序。
调试信息清楚的告诉我们,程序第7行存在问题:1、使用了未初始化的指针;2、非法访问指针。导致程序最后出现段错误。02
内存泄漏
test2.c
#include #include #include int main(){ int *p = (int *)malloc(sizeof(int) * 10); memset(p, 0, 10); return 0; }
运行结果:
加上【--leak-check=full】再次运行:
这次运行,明确指出了程序第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; }
运行结果:
程序中虽然使用了野指针,但是运行并没有出现段错误。这就是C语言内存管理不严格的地方,只有访问了系统保护的内存,才会出现段错误,虽然内存被释放了,但并没有被保护,所以就算访问,也不会出现问题。但是这种不合法的使用还是能被
valgrind
检测出来。
04
堆栈越界访问
test4.c
#include #include int main(){ char *p = (char *)malloc(sizeof(char) * 16); p[20] = 'x'; free(p); return 0; }
运行结果:
05
重复释放内存
test5.c
#include #include int main(){ char *p = (char *)malloc(sizeof(char) * 1024); free(p); free(p); return 0; }
运行结果:
06
new和delete
valgrind同样适用于C++程序,比如new和delete没有匹配使用、堆栈内存越界访问,用法和上面的一样,这里就不写代码了。总结
内存泄漏问题在定位问题的时候很难被发现,所以这个时候 valgrind 就可以发挥很大的力量。同时也要提醒大家,平时写代码的时候也要注意,申请了内存用完后一定要释放,就像去图书馆借书一样,光借不还,图书馆迟早要关门。养成良好的编码习惯,毕竟调试程序也很废脑子。PS.给小伙伴们汇报个事:
《春季智能硬件工程师培训班》
启动报名,限额25位
努力提升硬实力
备战秋招
有需要的小伙伴请提前报名锁定席位?