背景:
项目中遇到wifi偶发性打开失败的问题,但是可以确定的是驱动层是没有问题的,那么肯定就是中间层哪里出问题了,后面通过日志排查,大概能确定的是哪里存在句柄泄露了,导致wifi在调用socket的时候,由于句柄池已满,打开失败了,但是具体是哪里有句柄泄露,不好排查,最后还是在网上查到可以借助Valgrind,于是在加上调试信息后,敲valgrind --tool=memcheck --track-fds=yes ./your_program,最终定位到了问题。
Valgrind 基础介绍
Valgrind 是一款用于内存调试、内存泄漏检测及性能分析的工具集。其中 memcheck 是默认工具,用于检测内存泄漏和非法内存访问。
安装 Valgrind
在 Linux 系统中,可以通过包管理器安装:
sudo apt-get install valgrind # Debian/Ubuntu
sudo yum install valgrind # CentOS/RHEL
注意:嵌入式项目中,可以先make menuconfig看下系统有没有集成valgrind,如果有的话,需要选中,不然无法直接使用这个工具;如果没有集成这个工具,那就需要自己去打包源码,用项目工具链编译,然后下载到机器中了。
基本内存泄漏检测
以下是一个简单的 C 程序示例,包含内存泄漏问题:
// demo_leak.c
#include <stdlib.h>
void leak() {
malloc(10); // 未释放的内存
}
int main() {
leak();
return 0;
}
使用 Valgrind 检测内存泄漏:
gcc -g demo_leak.c -o demo_leak
valgrind --leak-check=full ./demo_leak
Valgrind 输出解析
Valgrind 的输出会显示以下关键信息:
- Definitely lost:明确的内存泄漏。
- Indirectly lost:间接内存泄漏(如结构体中指针未释放)。
- Possibly lost:可能的内存泄漏(指针指向内存中间位置)。
- Still reachable:程序结束时仍可访问的内存(通常为全局变量)。
检测句柄泄漏
句柄泄漏(如文件描述符未关闭)可以通过 valgrind 结合 --track-fds=yes 选项检测:
// demo_fd_leak.c
#include <fcntl.h>
#include <unistd.h>
void fd_leak() {
open("temp.txt", O_CREAT | O_RDWR, 0644); // 未关闭的文件描述符
}
int main() {
fd_leak();
return 0;
}
运行命令:
gcc -g demo_fd_leak.c -o demo_fd_leak
valgrind --track-fds=yes ./demo_fd_leak
检测系统库函数的内存泄漏
Valgrind 可以检测应用程序调用的系统库函数(如 glibc)中的内存泄漏。以下是一个调用 strdup 的示例:
// demo_lib_leak.c
#include <string.h>
#include <stdlib.h>
void lib_leak() {
char *s = strdup("hello"); // 未释放的内存
}
int main() {
lib_leak();
return 0;
}
运行命令:
gcc -g demo_lib_leak.c -o demo_lib_leak
valgrind --leak-check=full ./demo_lib_leak
Valgrind 常用命令选项
-
基本内存检查:
valgrind --leak-check=full ./your_program -
显示所有内存错误:
valgrind --tool=memcheck --show-reachable=yes ./your_program -
跟踪文件描述符:
valgrind --track-fds=yes ./your_program -
生成详细日志文件:
valgrind --log-file=valgrind.log --leak-check=full ./your_program -
忽略特定错误(如已知的库函数问题):
valgrind --suppressions=suppress.txt ./your_program
高级用法:抑制误报
某些系统库可能会触发误报。可以通过编写抑制文件忽略这些错误。例如:
# suppress.txt
{
<glibc_2.30_strdup>
Memcheck:Leak
fun:strdup
}
运行命令:
valgrind --suppressions=suppress.txt --leak-check=full ./your_program
实际案例:检测多线程内存泄漏
以下是一个多线程内存泄漏的示例:
// demo_thread_leak.c
#include <pthread.h>
#include <stdlib.h>
void *thread_func(void *arg) {
malloc(20); // 线程中未释放的内存
return NULL;
}
int main() {
pthread_t tid;
pthread_create(&tid, NULL, thread_func, NULL);
pthread_join(tid, NULL);
return 0;
}
运行命令:
gcc -g demo_thread_leak.c -o demo_thread_leak -lpthread
valgrind --leak-check=full ./demo_thread_leak
注意事项
- 编译时务必加上
-g选项以生成调试信息。 - Valgrind 会显著降低程序运行速度,仅用于调试环境。
- 对于大型项目,建议结合
--log-file将输出重定向到文件。
通过以上方法和示例,可以高效地使用 Valgrind 检测内存泄漏、句柄泄漏以及系统库函数的内存问题。
3万+

被折叠的 条评论
为什么被折叠?



