[openwrt] valgrind定位内存泄漏

news2025/1/15 13:30:21

目录

要求

valgrind

简介

工具介绍

linux程序的内存布局

内存检查的原理

valgrind的使用

使用举例

内存泄漏

内存越界

内存覆盖

Linux分配虚拟内存(申请内存)的两种方式

brk和mmap


要求

被调试程序带有-g参数编译,携带debug参数;

编译出valgrind程序,

valgrind

简介

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

 

工具介绍

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

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

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

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

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

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

linux程序的内存布局

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

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

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

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

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

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

内存检查的原理

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

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

Valid-Value 表

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

Valid-Address 表

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

检测原理

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

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

valgrind的使用

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

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

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

使用举例

内存泄漏

源程序

#include<stdio.h>

#include<stdlib.h>

int main()

{

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

return 0;

}

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

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

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

中间的红色方框表示 valgrind 通过运行被测试程序,发现的内存问题。通过阅读这些信息,可以发现: 发生错误时的函数堆栈,以及具体的源代码行号。非法写操作的具体地址空间。

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

内存越界

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行进行非法的写操作。

内存覆盖

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

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

#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++开发人员。

 

OpenWRT之Valgrind内存泄露检查参考文档 - Powered by MinDoc

内存检测王者之剑—valgrind - 知乎

valgrind --leak-check=full --show-reachable=yes --trace-children=yes /usr/bin/nr_ping_monitor&

运行valgrind程序报如下错误:

 

Linux-Level2-day03:内存映射及其分配释放函数brk/sbrk->mmap/munmap;系统调用过程详解;_mmap释放_dpq666dpq666的博客-CSDN博客

Linux分配虚拟内存(申请内存)的两种方式

Linux分配虚拟内存(申请内存)的两种方式_linux申请虚拟内存_TABE_的博客-CSDN博客

brk和mmap

从操作系统角度来看,malloc的实现有两种方式,分别由两个系统调用完成:brk和mmap(不考虑共享内存)。

申请小于128k的内存时,使用brk分配内存,将数据段.data的最高地址指针_edata向高地址移动,即增加堆的有效区域来申请新的内存空间。
申请大于128k的内存时,使用mmap分配内存,mmap是在进程的文件映射区找一块空闲存储空间,128K限制可由M_MMAP_THRESHOLD选项进行修改。
这两种方式分配的都是虚拟内存,没有分配物理内存。在第一次访问已分配的虚拟地址空间的时候,发生缺页中断,操作系统负责分配物理内存,然后建立虚拟内存和物理内存之间的映射关系。

brk和mmap的区别
malloc 通过 brk() 方式申请的内存,free 释放内存的时候,并不会把内存归还给操作系统,而是缓存在 malloc 的内存池中,待下次使用;同时brk分配的内存需要等到高地址内存释放以后才能释放,这也是内存碎片产生的原因
通过 mmap() 方式申请的内存,free 释放内存的时候,会把内存归还给操作系统,内存得到真正的释放。除此之外,mmap分配的内存可以单独释放。
 

malloc/calloc/realloc/free---> brk/sbrk ---> mmap/munmap--->kmalloc/kfree 即上层不断调用底层代码

调用sbrk(10)后堆顶往上移动10个字节,建立起内存映射关系与占优关系,别的进程不能非法占有

堆顶->-  -  -  -  -  -  -  -
           10字节
    -  -  -  -  -  -  -  -<-函数返回值
          堆区
     -----------------



调用sbrk(-10)释放10个字节内存,
     -  -  -  -  -  -  -  -<-返回值
         10字节
堆顶->-  -  -  -  -  -  -  -
          堆区
      -----------------


成功返回调用该函数之前的堆顶指针,失败返回-1。

increment
>0 - 堆顶指针上移,增大堆空间,分配虚拟内存
<0 - 堆顶指针下移,缩小堆空间,释放虚拟内存
=0 - 不分配也不释放虚拟内存,仅仅返回当前堆顶指针

系统内核维护一个指针,指向堆内存的顶端,顶端即有效堆内存中最后一个字节的下一个位置。sbrk函数根据增量参数increment调整该指针的位置,同时返回该指针原来的位置,期间若发生内存耗尽或空闲,则自动追加或取消相应内存页的映射。
 

利用Strace工具分析内存泄漏问题_strace检测内存泄露_权艺的博客-CSDN博客

strace -tt -f -e "brk,mmap,munmap" ./straceMemleak

strace -tt -f -e "brk"  /usr/bin/nr_ping_monitor -o /mnt/mtdbloc7/strace.txt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/467979.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二维码在数字化班组管理中的应用

为了更好地贯彻落实集团公司对班组安全建设的要求&#xff0c;可以运用“加法思维”&#xff0c;勇于直面当前安全班组建设中的突出问题&#xff0c;敢于创新和突破&#xff0c;自主搭建数字化班组管理平台&#xff0c;以进一步提升班组安全建设水平。 本文将详细介绍搭建设备…

腾讯云CDN的HTTPS服务是收费的?

腾讯云内容分发网络CDN的HTTPS请求数收费了&#xff0c;之前阿里云CDN是收费的&#xff0c;现在腾讯云HTTPS请求数也开始收费的&#xff0c;但是腾讯云还是很良心的每月300万次以内是不计费的&#xff0c;只有超出free额度的部分才另外收费&#xff0c;HTTPS请求数价格为0.05元…

Windows10资源管理器使用

文章目录 前言二、关联菜单操作1.分组展示2.添加选择复选框3.使用窗格模式4.功能区折叠二、“文件夹选项”对话框操作1.访问模式调整2.状态栏控制总结前言 目前Windows系统中的使用较多当属Windows10,资源管理器属于Windows系统中一个常用工具。本文总结了Windows 10 专业版下…

类的默认成员函数

为什么会有构造函数和析构函数呢&#xff1f; 1、初始化和销毁经常忘记 2、有些地方写起来很繁琐. Stack有了构造和析构&#xff0c;就不怕忘记写初始化和清理函数了&#xff0c;也简化了 例如在队列oj时&#xff0c;忘记释放&#xff0c;造成内存泄漏 构造函数 主要任务&am…

spark on k8s 部署的一点理解

Running Spark on Kubernetes - Spark 3.4.0 Documentation (apache.org) 前提条件 1. 本地有spark安装包&#xff0c;以便于执行 spark submit 命令 2. k8s 集群&#xff0c;以及本地的有 kubectl 并且配置的用户包含相关权限&#xff0c;具体可以参考官网 一些观念的转变 …

二百左右的蓝牙耳机哪款好?200左右音质最好的蓝牙耳机

在日常生活中离不开智能手机&#xff0c;特别是对无线蓝牙耳机的需求程度也越来越高&#xff0c;但是市面上有很多的蓝牙耳机戴久了耳朵会出现不舒服&#xff0c;为了获得更好的使用体验&#xff0c;我整理了市面上200左右价位佩戴和音质都表现不错的蓝牙耳机。 一、南卡小音舱…

Leetcode 并查集详解

在一些应用的问题中&#xff0c;需将n个不同的元素划分成一组不相交的集合。开始时&#xff0c;每个元素自成一格单元素集合&#xff0c;然后按一定顺序将属于同一组的元素的集合合并。其间要反复用到查询某个元素属于哪个集合的运算。适合于描述这类问题的抽象数据类型称为并查…

【22】linux进阶——文本处理工具:cut、awk、sed

大家好&#xff0c;这里是天亮之前ict&#xff0c;本人网络工程大三在读小学生&#xff0c;拥有锐捷的ie和红帽的ce认证。每天更新一个linux进阶的小知识&#xff0c;希望能提高自己的技术的同时&#xff0c;也可以帮助到大家 另外其它专栏请关注&#xff1a; 锐捷数通实验&…

一段凄惨Android 面试经历分享,败在了项目架构原理上……

大家应该看过很多分享面试成功的经验&#xff0c;但根据幸存者偏差的理论&#xff0c;也许多看看别人面试失败在哪里&#xff0c;对自己才更有帮助。 这是一位网友分享的面试经历&#xff0c;他准备了3个月&#xff0c;刚刚参加完字节跳动的第三面&#xff0c;视频面&#xff…

数说故事联合中山大学国际关系学院共建「国关数据实验室」,深化数据科学与国际关系融合创新

4月9日&#xff0c;数说故事联合中山大学国际关系学院共建的「国关数据实验室」正式启动&#xff0c;此次强强联合是双方在国际关系领域的一项创新尝试&#xff0c;该实验室旨在整合数说故事和国际关系学院师生的资源优势&#xff0c;将数据科学与国际关系研究相结合&#xff0…

真实还原美团4面经历,低学历成功拿到20K Offer...

个人背景 如标题所示&#xff0c;我的个人背景非常简单&#xff0c;软件测试经验 1 年半&#xff0c;学历普通&#xff0c;2 本毕业后出来就一直在做功能测试&#xff0c;在公司每天重复的工作对我的技术提升并没有什么帮助&#xff0c;但小镇出来的我也深知自我努力的重要性&…

Binder 与 四大组件工作原理 其一

Binder Binder的组成结构 Binder的架构如图所示 ServiceManager负责把Binder Server注册到一个容器中。 我们可以这样理解Client、Server 、ServiceManager、Binder Driver之间的关系&#xff1a; 把ServiceManager比喻成电话局&#xff0c;存储着每个住宅的座机电话。张三给…

记录-Vue移动端日历设计与实现

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 工作中遇到一个需求是根据日历查看某一天/某一周/某一月的睡眠报告&#xff0c;但是找了好多日历组件都不是很符合需求&#xff0c;只好自己手写一个日历组件&#xff0c;顺便记录一下。 先看看UI给的…

linux文件编辑与编辑命令

文章目录 一、linux文件编辑与编辑命令总结 一、linux文件编辑与编辑命令 Linux mkdir命令:创建目录 Linux more命令:显示文本文件内容 Linux cat命令:连接文件并打印到标准输出设备上 Linux grep命令:检索文件内容 Linux rm命令:删除文件或目录 Linux touch命令:修改文件的时…

15款时间计划、任务管理APP/软件对比(团队\个人)

15 款不同类型的日程、任务管理应用&#xff1a;1.PingCode&#xff1b;2.Worktile&#xff1b;3.Todoist&#xff1b;4.Trello&#xff1b;5.Microsoft To Do&#xff1b;6.Asana&#xff1b;7.Google 任务&#xff1b;8.Notion&#xff1b;9.Monday.com&#xff1b;10.Teambi…

Matlab对日期变量和时间变量的管理

Matlab2012a内置了三个函数 datanumdatevecdatestr 靠这三个函数&#xff0c;可以基本实现日期变量和时间变量的管理。下面直接来看。 &#xff08;1&#xff09;datanum 这个函数用来将字符串&#xff0c;日期矢量转为通用日&#xff08;数值型&#xff09;。所谓的通用日…

js特殊对象 - RegExp对象(正则表达式)

1、概述 正则表达式用于定义一些字符串的规则&#xff0c;计算机可以根据正则表达式&#xff0c;来检查一个字符串是否符合规则&#xff0c;获取将字符串中符合规则的内容提取出来。 使用typeof检查正则对象&#xff0c;会返回object。 2、创建正则对象 2.1、使用对象创建 语法…

Java spring 注解 @PostConstruct 实战讲解

前言 在最近的学习中&#xff0c;发现了一个非常实用的注解 —— PostConstruct。通过学习了解&#xff0c;逐步发现它能帮助我更轻松的解决不少原本很复杂的问题。 下面&#xff0c;结合实例介绍 PostConstruct 注解的特性&#xff0c;因为PreDestroy基本用不到&#xff0c;所…

C++算法初级11——01背包问题(动态规划2)

C算法初级11——01背包问题&#xff08;动态规划2&#xff09; 文章目录 C算法初级11——01背包问题&#xff08;动态规划2&#xff09;问题引入0-1背包问题分析0-1背包问题的形式化分析优化 问题引入 辰辰采药 辰辰是个天资聪颖的孩子&#xff0c;他的梦想是成为世界上最伟大…

Ubuntu开机自启动一些东西

有三种方式做开机自启动 目录 1.免除sudo密码 2.Startup 2.desktop 3.service 1.免除sudo密码 做完这一步你的所有sudo命令都不会再让你输密码了 如果你的开机自启动的东西需要sudo&#xff0c;那么这一步就是必须的&#xff0c;如果不需要sudo&#xff0c;那么这一步可…