ToB企服应用市场:ToB评测及商务社交产业平台

标题: Linux 下使用 Valgrind 举行内存调试 [打印本页]

作者: 道家人    时间: 2024-12-14 05:40
标题: Linux 下使用 Valgrind 举行内存调试

一、概述

Valgrind 是一个开源的内存调试和性能分析工具,用于帮助开发者找出程序中的内存错误,如内存走漏、使用未初始化的内存、非法内存访问等问题。它在 Linux 平台上广泛使用,而且支持下多种处置惩罚器架构。
二、Valgrind 的使用

1、基本格式

  1. valgrind --tool=memcheck -–gen-suppressions=all -–show-leak-kinds=all --log-file=<filename> --leak-check=yes ./your_app arg1 arg2...
复制代码

2、Valgrind 工具集

Valgrind 工具集包含多个工具,每个工具都针对不同的调试、分析和性能优化使命。以下是 Valgrind 工具会合一些常用的工具:
每个工具都有其特定的用途和上风,可以根据需要选择符合的工具来举行程序调试、性能优化或内存分析。
接下来主要是介绍 Memcheck 工具的使用。
3、Memcheck

Valgrind 在内存检测方面主要有四个使用场景:
3.1 使用未初始化的内存

首先看一个例子:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(){
  4.     char *p;
  5.     char c = *p;
  6.     printf("\n [%c]\n", c);
  7.     return 0;
  8. }
复制代码
可以看出,这里访问了一个野指针。接下来编译:
  1. $ gcc test
复制代码
然后使用 Valgrind 工具分析:
  1. $ valgrind --tool=memcheck ./a.out
复制代码
报错信息和出现错误的位置都打印了出来:

3.2 内存走漏

照旧先看代码:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(){
  4.     char *p = malloc(1);
  5.     *p = 'a';
  6.     char c = *p;
  7.     printf("\n [%c]\n", c);
  8.     return 0;
  9. }
复制代码
可以看到,这里为 p 指针申请了一个地址,不过末了没有 free 掉这个地址就 return 0 了,也就是会照成内存走漏。先编译:
  1. $ gcc test
复制代码
然后使用 Valgrind 工具分析:
  1. $ valgrind --tool=memcheck --leak-check=full ./a.out
复制代码
效果如下,可以看到提示信息显示 alloc 了 2 次,但却只 free 1 次,以是发生了内存走漏,再下面是内存走漏的详细信息。

3.3 在内存被开释后举行读/写

示例代码如下:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(){
  4.     char *p = malloc(1);
  5.     *p = 'a';
  6.     char c = *p;
  7.     printf("\n [%c]\n", c);
  8.     free(p);
  9.     c = *p;
  10.     return 0;
  11. }
复制代码
编译后,用 vallgrind 查察:
  1. $ gcc test
  2. .c$ valgrind --tool=memcheck ./a.out
复制代码
上面的代码中,我们有一个开释了内存的指针 p,然后我们又实验使用指针获取值。从下面的输出内容可以看到,Valgrind 检测到了无效的读取操作然后输出了告诫"Invalid read of size 1’.

3.4 内存块的尾部举行读/写

代码如下:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(){
  4.     char *p = malloc(1);
  5.     *p = 'a';
  6.     char c = *(p+1);
  7.     printf("\n [%c]\n", c);
  8.     free(p);
  9.     return 0;
  10. }
复制代码
  1. $ gcc test
  2. .c$ valgrind --tool=memcheck ./a.out
复制代码
可以看到,这里仍旧是非法的读,因为我们只申请了 1 个字节空间:

4、常见错误

下面是一些日志打印中常见的错误:

三、分析内存走漏的使用本领

1、Valgrind 调和 GDB 工作

在 Linux 内存走漏的排查过程中,Valgrind 和 GDB 的联合使用是一种强大的调试策略。Valgrind 可以或许帮助我们发现程序中的内存走漏,而 GDB 则允许我们深入程序的实行,查察变量和内存状态,从而精确地定位问题。
Valgrind 提供了一个 --vgdb-error=0 的选项,允许我们在第一个错误发生时立即启动 GDB。如许,我们可以在程序实行到大概出现内存走漏的地方时,立即举行检查。
下面是操作流程:
  1. $ valgrind --tool=memcheck --vgdb=yes --vgdb-error=0 ./a.out
复制代码
  1. $ gdb ./a.out
  2. (gdb) target remote | vgdb
复制代码
2、使用 /proc 定位问题

Linux 的 /proc 文件体系包含了体系运行时的各种信息,其中也包罗了历程的内存映射情况。通太过析 /proc/[pid]/maps 文件,我们可以得知历程的内存分配情况,这对于定位内存走漏非常有用。
每个历程的 /proc/[pid]/maps 文件都记录了该历程的内存映射。我们可以通过以下下令查察特定历程的内存映射:
  1. $ cat /proc/[pid]/maps
复制代码
[pid] 需要替换为我们怀疑存在内存走漏的历程ID。通太过析这个文件,我们可以看到历程的内存分配情况,包罗哪些库文件被加载,以及它们的内存地址范围。

从左向右的六列数据的含义如下:

如果发生内存走漏,表格中的某些行会显示出异常的模式,特殊是在堆大概大概的匿名映射(通常是堆或栈的扩展)区域。以下是一些大概表明内存走漏的情况:
好比,下列数据展示了大概的内存走漏的情况:
  1. 02557000-03578000           rw-p 00000000 00:00 0                [heap]
  2. ...
  3. 7ff3c8c00000-7ff3c8e21000        rw-p 00000000 00:00        0       
复制代码
在这个例子中,我们看到:

3、使用 top、ps 识别异常历程

3.1 使用 top

  1. $ top -o %MEM
复制代码
这个下令会将历程按内存使用率举行排序,帮助我们更快地定位到内存使用异常的历程。
在使用 top 下令观察历程的内存使用情况时,我们需要关注的是内存使用量(RES)和虚拟内存使用量(VIRT)。内存走漏通常表现为随着时间的推移,这两个值会不断增长。

3.2 使用 ps

我们可以使用 ps 下令的 -o 选项来自定义输出,以便专注于内存相干的信息。例如:
  1. $ ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem
复制代码
这个下令将列出全部历程,并按内存使用率降序分列,显示每个历程的 PID、PPID、下令行、内存使用率和 CPU 使用率。
联合历史数据,我们可以分析历程的内存使用趋势。通过定期记录 ps 下令的输出,我们可以创建一个内存使用的时间序列,这有助于我们识别内存走漏的长期趋势。
  1. #! /bin/sh
  2. while true; do
  3.         ps -eo pid,cmd,%mem,%cpu --sort=-%mem | head -n 10 >> memory_usage.log;
  4.         sleep 60;
  5. done
复制代码
这段脚本会每分钟记录内存使用最高的 10 个历程,并将效果追加到 memory_usage.log 文件中。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4