前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >内存检测王者之剑—valgrind

内存检测王者之剑—valgrind

作者头像
233333
发布于 2021-08-05 06:37:02
发布于 2021-08-05 06:37:02
1.8K00
代码可运行
举报
运行总次数:0
代码可运行

记得在大学的刚开始学习C/C++的时候,对于内存问题一点也没有关心过,其实也是关心比较少,知道后来才慢慢注意起来,当时排查是否有内存泄漏全靠手,去看看malloc和free或者new和delete是否对应起来,这也是一种比较简单的查询是否有内存泄漏的办法,后来老师提供了一种用程序来检测是否有内存泄漏,其实就是重载new和delete的方法。

今天,我们一起来学习一下强大的内存检测工具----valgrind。

1. valgrind简介

Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合。Valgrind由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),它模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件 (plug-in),利用内核提供的服务完成各种特定的内存调试任务。Valgrind的体系结构如下图所示:

2.valgrind工具

(1)Memcheck。这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。这也是本文将重点介绍的部分。

(2)Callgrind。它主要用来检查程序中函数调用过程中出现的问题。

(3)Cachegrind。它主要用来检查程序中缓存使用出现的问题。

(4)Helgrind。它主要用来检查多线程程序中出现的竞争问题。

(5)Massif。它主要用来检查程序中堆栈使用中出现的问题。

(6)Extension。可以利用core提供的功能,自己编写特定的内存调试工具。

这个里面我们主要用就是第一个memcheck.

3. linux程序的内存布局

首先,我们来看看内存分配图

(1)代码段(.text)。这里存放的是CPU要执行的指令。代码段是可共享的,相同的代码在内存中只会有一个拷贝,同时这个段是只读的,防止程序由于错误而修改自身的指令。

(2)初始化数据段(.data)。这里存放的是程序中需要明确赋初始值的变量,例如位于所有函数之外的全局变量:int val=100。需要强调的是,以上两段都是位于程序的可执行文件中,内核在调用exec函数启动该程序时从源程序文件中读入。当然也少不了静态变量。

(3)未初始化数据段(.bss)。位于这一段中的数据,内核在执行该程序前,将其初始化为0或者null。例如出现在任何函数之外的全局变量:int sum;

(4)堆(Heap)。这个段用于在程序中进行动态内存申请,例如经常用到的malloc,new系列函数就是从这个段中申请内存。

(5)栈(Stack)。函数中的局部变量以及在函数调用过程中产生的临时变量都保存在此段中。

4. 内存检查的原理

Memcheck检测内存问题的原理如下图所示:

Memcheck 能够检测出内存问题,关键在于其建立了两个全局表。

1.Valid-Value 表:

对于进程的整个地址空间中的每一个字节(byte),都有与之对应的 8 个 bits;对于 CPU 的每个寄存器,也有一个与之对应的 bit 向量。这些 bits 负责记录该字节或者寄存器值是否具有有效的、已初始化的值。

2.Valid-Address 表

对于进程整个地址空间中的每一个字节(byte),还有与之对应的 1 个 bit,负责记录该地址是否能够被读写。

检测原理:

当要读写内存中某个字节时,首先检查这个字节对应的 A bit。如果该A bit显示该位置是无效位置,memcheck 则报告读写错误。

内核(core)类似于一个虚拟的 CPU 环境,这样当内存中的某个字节被加载到真实的 CPU 中时,该字节对应的 V bit 也被加载到虚拟的 CPU 环境中。一旦寄存器中的值,被用来产生内存地址,或者该值能够影响程序输出,则 memcheck 会检查对应的V bits,如果该值尚未初始化,则会报告使用未初始化内存错误。

5.valgrind的使用

为了使valgrind发现的错误更精确,如能够定位到源代码行,建议在编译时加上-g参数,编译优化选项请选择O0,虽然这会降低程序的执行效率。

1.利用valgrind调试内存问题,不需要重新编译源程序,它的输入就是二进制的可执行程序。调用Valgrind的通用格式是:valgrind [valgrind-options] your-prog [your-prog-options]

2.Valgrind 的参数分为两类,一类是 core 的参数,它对所有的工具都适用;另外一类就是具体某个工具如 memcheck 的参数。Valgrind 默认的工具就是 memcheck,也可以通过“--tool=tool name”指定其他的工具。Valgrind 提供了大量的参数满足你特定的调试需求,具体可参考其用户手册。

1:未释放内存

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<stdio.h>

#include<stdlib.h>



int main()

{

int *array = malloc(sizeof(int));



return 0;

}

执行命令:valgrind --tool=memcheck --leak-check=full ./1

1.左边显示类似行号的数字(2847)表示的是 Process ID

2.最上面的红色方框表示的是 valgrind 的版本信息

3.中间的红色方框表示 valgrind 通过运行被测试程序,发现的内存问题。通过阅读这些信息,可以发现:

发生错误时的函数堆栈,以及具体的源代码行号。

非法写操作的具体地址空间。

4.最下面的红色方框是对发现的内存问题和内存泄露问题的总结。内存泄露的大小(4 bytes)也能够被检测出来。

2.内存越界

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<stdio.h>

#include<stdlib.h>



int main()

{

int i;

int len = 4;

int *pt = (int*)malloc(len*sizeof(int));

int *p = pt;



for(i=0;i<len;i++)

{

p++;

}



*p = 5;

return 0;

}

执行命令:valgrind ./2



==2918== Invalid write of size 4

==2918== at 0x400570: main (2.c:16)

==2918== Address 0x5204050 is 0 bytes after a block of size 16 alloc'd

==2918== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==2918== by 0x400545: main (2.c:8)

我们发现valgrind准确的定位了问题,在16行进行非法的写操作。

3.内存覆盖

C 语言的强大和可怕之处在于其可以直接操作内存,C 标准库中提供了大量这样的函数,比如 strcpy, strncpy, memcpy, strcat 等,这些函数有一个共同的特点就是需要设置源地址 (src),和目标地址(dst),src 和 dst 指向的地址不能发生重叠,否则结果将不可预期。

下面就是一个 src 和 dst 发生重叠的例子。在 15中,src 和 dst 所指向的地址相差 20,但指定的拷贝长度却是 21,这样就会把之前的拷贝值覆盖。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<string.h>

#include<stdio.h>

#include<stdlib.h>



int main()

{

char x[50];

int i;

for(i=0;i<50;i++)

{

x[i] = i+1;

}



strncpy(x+20,x,20);

strncpy(x+20,x,21);

return 0;

}

2976 Source and destination overlap in strncpy(0xfff0003f9, 0xfff0003e5, 21)

2976 at 0x4C31626: __strncpy_sse2_unaligned (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

2976 by 0x400608: main (3.c:15)

输出结果显示上述程序中第15,源地址和目标地址设置出现重叠。准确的发现了上述问题。

总结:由此可知,valgrind是一款非常强大的内存泄漏检测工具,在我们的项目和学习中有很大的作用,尤其是从事C/C++开发人员。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-07-29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Linux 命令(143)—— valgrind 命令
Valgrind 工具套件提供了许多调试和分析工具,可帮助您使程序更快、更正确。 这些工具中最受欢迎的称为 Memcheck。 它可以检测 C 和 C++ 程序中常见的许多与内存相关的错误,这些错误可能导致崩溃和不可预知的行为。
恋喵大鲤鱼
2022/10/07
3.5K0
【Linux】内存检测工具Valgrind
内存检测工具Valgrind Valgrind是运行在Linux上的一套基于仿真技术的程序调试和分析工具,作者是获得过Google-O’Reilly开源大奖的Julian Seward,它包含一个内核——一个软件合成的CPU,和一系列的小工具,每个工具都可以完成一项任务——调试,分析,测试等。 内存检测,使用它的Memcheck工具。 ---- Valgrind安装 官网 http://valgrind.org ubuntu sudo apt-get install valgrind ----
半生瓜的blog
2023/05/13
3.2K0
【Linux】内存检测工具Valgrind
C/C++生态工具链——内存泄露检测工具Valgrind
Valgrind提供了很多组件,这些组件可以用来分析和调试程序、检测内存是否正常使用、分析程序的性能等。Valgrind有自己的内核,它可以提供一个虚拟的CPU来运行程序,并完成程序的调试和剖析等任务。
Coder-ZZ
2023/02/23
6.2K0
C/C++生态工具链——内存泄露检测工具Valgrind
Linux下检测内存泄露的工具 valgrind
参考:http://www.cnblogs.com/sunyubo/archive/2010/05/05/2282170.html 几乎是照抄参考过来的,只不过后面自己调试一下代码。 这里主要介绍Valgrind的一些简单用法。更多详细的使用方法可以访问valgrind的主页:http://www.valgrind.org Valgrind是Julian Seward的作品。Valgrind是运行在Linux上一套基于仿真技术的程序调试和分析工具,它包含一个内核,一个软件合成的CPU,和一系列的小工具。 每
xcywt
2018/03/28
6.2K0
Linux下检测内存泄露的工具 valgrind
内存检测工具Valgrind
Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合。Valgrind由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),它模拟了
张善友
2018/01/22
2.5K0
内存检测工具Valgrind
valgrind使用:检测内存泄漏
07 Nov 2016 valgrind使用:检测内存泄漏 本文简单介绍c开发中的内存泄漏和动态内存分配函数,并使用valgrind分析c程序的内存泄漏问题。 1 什么是内存泄漏 c语言中,需由开发者负责内存的申请和释放,内存泄漏是指开发者在程序中使用动态内存分配函数xxlloc在堆(heap)上申请内存,内存在使用完毕后未使用free函数释放,那么这块内存在程序退出前都不能再次使用,导致内存使用逐渐增大,直至耗尽,程序异常退出。 xxlloc函数指mal
俊采
2018/05/15
2.5K0
valgrind使用:检测非法读写内存
14 Nov 2016 valgrind使用:检测非法读写内存 本文简单介绍如何通过valgrind检测c语言中的非法读写内存,避免发生不可预测行为。 1 什么非法读写内存 1.1 非法写内存 非法写内存是指往不属于程序分配的内存中写入数据。比如malloc一段内存,大小只有5个字节,那么你只能往这5个字节空间写入数据(如果是拷贝字符串,只能写4个字节),在这5字节的内存空间之外写入数据,都是非法的。比如写数组时越界,拷贝字符串时忘记结尾结束符。 1.2 非
俊采
2018/05/15
3.1K0
谈谈如何利用 valgrind 排查内存错误
Valgrind 最为开发者熟知和广泛使用的工具莫过于 Memcheck,它是检查 c/c++ 程序内存错误的神器,报告结果非常之精准。
范蠡
2020/07/30
7.7K0
谈谈如何利用 valgrind 排查内存错误
技术解码 | 内存问题的分析与定位
本期的技术解码,为您解析 编程中,内存问题的分析与定位方法 对编程语言设计来说,内存管理分为两大类:手动内存管理(manual memory management) 和垃圾回收(garbage collection). 常见的如C、C++使用手动内存管理,Java使用垃圾回收。本文主要关注手动内存管理。 GC GC使内存管理自动化,缺点是引入了GC时不可预测的暂停(unpredictable stall),对实时性要求高的场景不适用。现代的GC实现一直朝着减小“stop-the-world"影
腾讯云音视频
2021/04/29
4.5K0
Unix下c程序内存泄露检测工具
Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。 Valgrind的最初作者是Julian Seward,他于2006年由于在开发Valgrind上的工作获得了第二届Google-O'Reilly开源代码奖。 Valgrind遵守GNU通用公共许可证条款,是一款自由软件。 官网 http://www.valgrind.org 下载与安装 #wget http://www.valgrind.org/downloads/valgrind-3.8.1.tar.bz2 #tar xvf
猿人谷
2018/01/17
1.5K0
Unix下c程序内存泄露检测工具
valgrind使用介绍
-O0 、-O1 、-O2 、-O3 编译器的优化选项的 4 个级别,-O0 表示没有优化, -O1 为默认值,-O3 优化级别最高。
yzh
2020/08/04
3.3K0
千万不要错过的后端【纯干货】面试知识点整理 I I
内存泄漏,是由于疏忽或错误造成程序未能释放掉不再使用的内存。内存泄漏,并不是指内存内存在物理地址上的消失,而是应用程序分配某段内存后,失去了对该段内存的控制,因而造成内存的浪费。
阿兵云原生
2023/02/16
8290
nginx下使用asan和valgrind两个静态检查工具
valgrind安装:参考:https://blog.csdn.net/justheretobe/article/details/52986461
用户1215536
2019/09/25
1.8K0
堆状态分析的利器——valgrind的DHAT
在《堆问题分析的利器——valgrind的massif》一文中,我们介绍了如何使用massif查看和分析堆分配/释放的问题。但是除了申请和释放,堆空间还有其他问题,比如堆空间的使用率、使用周期等。通过分析这些问题,我们可以对程序代码进行优化以提高性能。本文介绍的工具DHAT——dynamic heap analysis tool就是分析这些问题的利器。(转载请指明出于breaksoftware的csdn博客)
方亮
2019/01/16
7950
finished with exit code -1073740791 (0xC0000409)
在进行编程开发过程中,我们有时候会遇到一些错误和异常情况。其中之一是程序运行时出现了异常退出,并显示 "finished with exit code -1073740791 (0xC0000409)" 的错误信息。本篇博客文章将详细介绍这个错误的原因和可能的解决方法。
大盘鸡拌面
2023/11/15
3.3K0
记一次openssl使用不当引发的内存泄漏
前言:本文记录一起第三方库使用不当引发的内存泄漏的定位过程。在日常工作中新写服务或者代码引发的内存泄漏还是相对较好定位的,因为这种情况下改动范围相对明确。但有时候也会面临从未动过的服务发生内存泄漏,这意味着这个服务很早就引入了内存泄漏,引发内存泄漏的范围相当不聚焦,这个时候很多同学就不知道如何下手。本文主要展现:①展现面对内存泄漏问题的定位及思考过程 ②综合利用wiresharks、jmeter等工具进行效果验证。
鹅厂老五
2024/06/16
5831
【C语言指南】C语言内存管理 深度解析
在C语言中,内存分配主要有两种方式:静态分配和动态分配。下面详细介绍这两种方式及其代码示例。
倔强的石头
2024/12/06
2700
【C语言指南】C语言内存管理 深度解析
C++内存问题排查攻略
GCC提供了-fstack-usage选项,能输出每个函数栈的最大使用量。开启后,为每个编译目标创建.su文件,每行包括函数名、字节数、修饰符(static/dynamic/bounded)中的一个或多个。修饰符的含义如下:
腾讯技术工程官方号
2024/08/14
3530
C++内存问题排查攻略
【C语言】解决C语言报错:Array Index Out of Bounds
Array Index Out of Bounds(数组索引越界)是C语言中常见且危险的错误之一。它通常在程序试图访问数组中不合法的索引位置时发生。这种错误会导致程序行为不可预测,可能引发段错误(Segmentation Fault)、数据损坏,甚至安全漏洞。本文将详细介绍Array Index Out of Bounds的产生原因,提供多种解决方案,并通过实例代码演示如何有效避免和解决此类错误。
E绵绵
2024/06/23
5180
堆问题分析的利器——valgrind的massif
堆问题也是内存问题的一部分。如果我们发现程序内存一直在增加,怀疑是内存泄漏,则可以使用《内存问题分析的利器——valgrind的memcheck》一文中介绍的“内存泄露”方法去分析定位。当然我们还可以使用本文介绍的工具——massif。(转载请指明出于breaksoftware的csdn博客)
方亮
2019/01/16
5.9K0
推荐阅读
相关推荐
Linux 命令(143)—— valgrind 命令
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验