简介
从第一篇文章我们知道,乐鑫官方给集成了一个调试工具,能够在程序异常时分层追踪到导致异常的地方。这个功能实际上很像Valgrind,她是一个在 Linux 环境下广泛使用的编程工具套件,主要用于内存调试、内存泄漏检测以及性能分析。它对于识别程序中的内存和线程问题非常有用,特别适用于 C 和 C++ 程序的开发和调试。在实际的开发过程当中如果遇到不好找的问题特别是崩溃内存泄漏等等,用这个工具是非常能够提高效率的。
安装 Valgrind
在大多数 Linux 发行版中,Valgrind 可以通过包管理器轻松安装。
- 在 Debian 或 Ubuntu 上:
sudo apt-get install valgrind
- 在 Fedora 或 CentOS 上:
sudo dnf install valgrind
基本使用
在使用 Valgrind 前,确保你的程序是带有调试信息的。使用 -g
标志编译,我们这里先用一个正常的代码举例
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main()
{
// unsigned char *test = NULL;
// *test = 28;
printf("hello word! \n");
}
root@song:~/mywork/Valgrind# valgrind --leak-check=full ./test
==317286== Memcheck, a memory error detector
==317286== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==317286== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==317286== Command: ./test
==317286==
hello word!
==317286==
==317286== HEAP SUMMARY:
==317286== in use at exit: 0 bytes in 0 blocks
==317286== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==317286==
==317286== All heap blocks were freed -- no leaks are possible
==317286==
==317286== For lists of detected and suppressed errors, rerun with: -s
==317286== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
root@song:~/mywork/Valgrind#
大家可以看到我在执行可执行文件之前,使用了valgrind --leak-check=full命令,这个命令的作用就是检查程序运行的过程当中是否有内存泄漏或者无效访问。接下来我来给大家演示一下使用valgrind工具来定位问题点的方法,首先还是来一个必然会出现段错误的代码,经典的往空指针中赋值
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main()
{
unsigned char *test = NULL;
*test = 28;
printf("hello word! \n");
}
使用gcc带 -g
编译并运行,我们会发现报段错误
root@song:~/mywork/Valgrind# gcc main.c -g -o test
root@song:~/mywork/Valgrind# ./test
Segmentation fault (core dumped)
接下来我们使用valgrind工具来检测一下是哪里出现了问题
root@song:~/mywork/Valgrind# valgrind --leak-check=full ./test
==317466== Memcheck, a memory error detector
==317466== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==317466== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==317466== Command: ./test
==317466==
==317466== Invalid write of size 1
==317466== at 0x109161: main (main.c:9)
==317466== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==317466==
==317466==
==317466== Process terminating with default action of signal 11 (SIGSEGV)
==317466== Access not within mapped region at address 0x0
==317466== at 0x109161: main (main.c:9)
==317466== If you believe this happened as a result of a stack
==317466== overflow in your program's main thread (unlikely but
==317466== possible), you can try to increase the size of the
==317466== main thread stack using the --main-stacksize= flag.
==317466== The main thread stack size used in this run was 8388608.
==317466==
==317466== HEAP SUMMARY:
==317466== in use at exit: 0 bytes in 0 blocks
==317466== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==317466==
==317466== All heap blocks were freed -- no leaks are possible
==317466==
==317466== For lists of detected and suppressed errors, rerun with: -s
==317466== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
root@song:~/mywork/Valgrind#
最终我们可以看到,valgrind的输出提示在main.c的第九行有一个针对地址0的操作。
==317466== Access not within mapped region at address 0x0
==317466== at 0x109161: main (main.c:9)
总结
我觉得还是没啥要总结的,不过这玩意儿确实是是个很好用的工具,毕竟商业项目不可能只有几百行代码,如果真的一不小心操作了空指针也是很难查的。在此,我继续让我儿冯正淳给大家磕个响头