聊一聊 Valgrind 监视非托管内存泄露和崩溃

news2024/11/20 6:15:14

一:背景

1. 讲故事

只要是程序总会出现各种莫名其妙的问题,比如:非托管内存泄露,程序崩溃,在 Windows 平台上一般用微软自家的官方工具 App Verifier 就可以洞察,那问题出在 Linux 上怎么办呢?由于 Linux 崇尚自由,需要在各种牛鬼蛇神写的非官方开源软件中寻找一个比较靠谱的,比如本篇所说的 Valgrind

个人感觉 ValgrindApp Verifer 定位是差不多的,技术上前者使用 hook 钩子,后者使用仿真cpu,有点像 windbg 的 TTD 调试,具体信息参考:https://valgrind.org/

二:Valgrind 内存洞察

1. 安装

如果你用的是 ubuntu,可以用 apt-get 直接安装,方便快捷,目前最新的版本是 3.15.0


root@skyfly-virtual-machine:/home/skyfly/Desktop# apt-get install valgrind
Reading package lists... Done
Building dependency tree       
Reading state information... Done
valgrind is already the newest version (1:3.15.0-1ubuntu9.1).
0 upgraded, 0 newly installed, 0 to remove and 23 not upgraded.

root@skyfly-virtual-machine:/home/skyfly/Desktop# valgrind --version
valgrind-3.15.0

2. 内存泄露洞察

内存泄露大多是 new/delete , malloc/free 不匹配造成的,接下来写一个不匹配的 malloc/free 观察下。


#include <iostream>
#include <stdio.h>

using namespace std;

int main(void)
{
    int *p = (int *)malloc(4);
    *p = 10;
    
    printf("p=%d", *p);

    return EXIT_SUCCESS;
}

这里使用 vscode 进行编译,怎么编译就不说了,参见上一篇,接下来用 algrind --leak-check=full ./main.out 以仿真的方式把程序跑起来,截图如下:

从图中的 HEAP SUMMARY 区域可以看到,当前有 3 个 malloc,但只有 2 个 free,而且还找到了那个没有 free 的 malloc,在代码的 main.cpp:8 行,即 int *p = (int *)malloc(4); 处。

3. 栈溢出洞察

相信经常写递归的朋友总会遇到这类问题,为了方便演示,我故意实现一个 栈上溢 的例子吧。


#include <iostream>
#include <stdio.h>

using namespace std;

int main(void)
{
    int num = 10;
    int *ptr = &num;

    ptr -= 0x40;
    *ptr = 15;

    return EXIT_SUCCESS;
}

从图中可以清晰的看到,主线程栈上的地址 0x1ffefffd5c 无法写入,还指出了在 main.cpp:12 行,即 *ptr = 15; 处。

为了方便验证,这里用 g++ 调试的方式洞察一下。


-exec p num
$5 = 10

-exec x ptr
0x7fffffffde2c:	0xf7fb0e9800007fff

-exec info reg
...
rbp            0x7fffffffdf40      0x7fffffffdf40
rsp            0x7fffffffdf20      0x7fffffffdf20
...

从输出看,ptr 已经逃出了 rsp ~ rbp 范围之内,很明显上溢了,如果用 x 命令观察的话,可以看到里面的内容就很随机,在 windbg 中用以 ??? 来表示的。


-exec x ptr
0x7fffffffde2c:	0xf7fb0e9800007fff

-exec x 0xf7fb0e9800007fff
0xf7fb0e9800007fff:	Cannot access memory at address 0xf7fb0e9800007fff

除了观察 rsp,rbp,还可以看虚拟地址中的 stack 空间。


-exec i proc mapping
process 8327
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
      ...
	  0x7ffff7ffd000     0x7ffff7ffe000     0x1000    0x2d000 /usr/lib/x86_64-linux-gnu/ld-2.31.so
      0x7ffff7ffe000     0x7ffff7fff000     0x1000        0x0 
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]

4. 数组越界洞察

valgrind 这玩意也有弱鸡的时候,比如数组越界之类的问题它就搞不定,比如下面的代码:


#include <iostream>
#include <stdio.h>

using namespace std;

int main(void)
{
    int num[5] = {1, 2, 3, 4, 5};
    int num2[10];

    num[6] = 15;

    return EXIT_SUCCESS;
}

通过下面的汇编代码观察,可以看到目前分配了 0x30 = 0n48 byte 的栈空间,截图如下:

虽然 num[6] 是越界操作,但是在合理的 栈空间 内,这种仿生cpu的方式洞察不出来,App Verifier 这种 hook 的方式是没有问题的。

接下来用 valgrind 尝试一下,可以看到果然没发现任何问题,输出如下:


skyfly@skyfly-virtual-machine:~/code$ valgrind ./main.out
==10244== Memcheck, a memory error detector
==10244== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10244== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==10244== Command: ./main.out
==10244== 
==10244== 
==10244== HEAP SUMMARY:
==10244==     in use at exit: 0 bytes in 0 blocks
==10244==   total heap usage: 1 allocs, 1 frees, 72,704 bytes allocated
==10244== 
==10244== All heap blocks were freed -- no leaks are possible
==10244== 
==10244== For lists of detected and suppressed errors, rerun with: -s
==10244== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

三:总结

总的来说,Valgrind 在洞察内存方面还是非常强大的,但也有它不能触及到的地方,熟悉它的优点和缺点,全面了解对我们调试师来说至关重要,希望本篇对你有帮助。

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

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

相关文章

块状链表实现BigString大字符串操作(golang)

前言 块状链表是介于链表和数组之间的数据结构&#xff0c;能够在 O ( n ) O(\sqrt{n}) O(n ​)时间内完成插入、删除、访问操作。 数据结构如图所示。假设最大容量为 n n n, 则它有一个长度为 s n s\sqrt{n} sn ​的链表。链表中每个结点是一个长度为 2 n 2 \times \sqrt{…

C#_各类应用程序

目录 前言 1. 第一个程序&#xff1a;Hello&#xff0c;World&#xff01; 1.1 Console 1.2 Windows Forms 1.3 WPF&#xff08;Windows Presentation Foundation&#xff09; 1.4 ASP.NET Web Forms 1.5 ASP.NET MVC(Model - View - Controller) 1.6 Windows Store A…

Tuxera NTFS2023Mac专业NTFS驱动软件 解决Mac不能写入移动硬盘U盘问题 管理修复磁盘

Tuxera NTFS2023Mac专业NTFS驱动软件 解决Mac不能写入移动硬盘U盘问题 管理修复磁盘问题! NTFS For Mac2023是一款功能强大的MAC读写软件。NTFS For Mac可以帮助用户对磁盘进行日常管理&#xff0c;如果用户电脑的磁盘有问题&#xff0c;可以使用该软件进行修复&#xff0c;延…

Chatgpt系列(一) 如何使用chatgpt

系列文章目录 第一章: 如何使用chatgpt 第二章: chatgpt的概述 第三章: langchain入门 第四章: index 第五章: prompt 目录 系列文章目录 前言 一、LLM是什么&#xff1f; 二、使用步骤 1.学习地址 2.阅读内容重点的介绍 2.答复 读入数据 总结 系列文章目录前言一…

0基础学Java必备的50个知识点

1、编写&#xff1a;编写的Java代码保存在以“.java”结尾的源文件中。 2、编译&#xff1a;使用javac.exe命令编译java源文件&#xff0c;生成字节码文件。 格式&#xff1a;javac 源文件名.java 3、运行&#xff1a;使用java.exe命令解释运行字节码文件。格式&#xff1a;…

Linux笔记3

目录 一、root用户1.su命令2.sudo命令 二、vi/vim编译器1.三种工作模式2.命令模式3.底线命令模式 三、用户和用户组1.用户组管理2.用户管理3.getent命令 四、权限1.查看权限控制信息2.chmod 命令3.chown 命令 五、常用快捷键1.Ctrlc2.Ctrld3.历史命令4.光标移动快捷键 一、root…

亚马逊云科技和安恒信息,发布云原生SaaS主机安全和云原生堡垒机

4月19日&#xff0c;安恒信息首次举行了以“新见未来 实现梦想”为主题的年度新品发布会。来自产业界、投资界、财经界、媒体界等多方代表共同见证了本次发布会。这也是安恒信息自成立以来&#xff0c;首次大规模、高密度地发布新品。 联合产品发布 云原生SaaS主机安全与云原…

Linux 指令(一)+完整思维导图+实图例子+深入细节+通俗易懂建议收藏

绪论 在上一章&#xff0c;我们已经将Linux环境的安装起来了&#xff0c;从本章开始&#xff0c;我们将正式的进入到Linux的学习&#xff0c;Linux的学习还是比较的枯燥无味的&#xff0c;但我们要吃得苦中苦&#xff0c;让我们一起加油&#xff0c;进大厂拿到心仪的offer&…

黑马程序员-职工管理系统实战-附加源码Git

1、管理系统需求 职工管理系统可以用来管理公司内所有员工的信息 本教程主要利用C来实现一个基于多态的职工管理系统 公司中职工分为三类&#xff1a;普通员工、经理、老板&#xff0c;显示信息时&#xff0c;需要显示职工编号、职工姓名、职工岗位、以及职责 普通员工职责…

Redis在项目实践中的问题解决方案汇总

前言 无论是在开发过程中还是在准备跑路的面试过程中&#xff0c;和Redis相关的话题&#xff0c;难免会涉及到四个特殊场景&#xff1a;缓存穿透、缓存雪崩、缓存击穿以及数据一致性。 虽然在作为服务缓存层的时候Redis确实能极大减少服务端的请求压力&#xff0c;但是如果在…

企业组织管理神器:红海云可视化组织管理功能深度解析

在当前的VUCA时代&#xff0c;企业需要保持敏捷以应对变革和不确定性。组织架构作为承载战略目标的重要工具&#xff0c;如果无法敏捷调整&#xff0c;会直接影响企业战略的成功落地。但组织架构的设计和调整会触及其他业务&#xff0c;包括岗位、编制、人员与汇报关系等信息变…

优先级队列(大根堆与小根堆)

优先级队列&#xff08;大根堆与小根堆&#xff09; 文章目录 优先级队列&#xff08;大根堆与小根堆&#xff09;堆的介绍模拟堆以数组模型为例&#xff0c;创建堆向下调整&#xff08;shiftDown&#xff09;入队&#xff08;push&#xff09;及向上调整&#xff08;shiftUp&a…

java获取文件夹下所有文件名

在进行 Java编程的过程中&#xff0c;我们会经常使用到文件夹下的所有文件名。有时候可能不太熟悉 Java编程的小伙伴们会发现&#xff0c;在代码中没有获取到所有的文件名&#xff0c;那么这个时候我们应该怎么去获取到这些文件呢&#xff1f;在进行 Java编程的过程中&#xff…

《花雕学AI》31:ChatGPT--用关键词/咒语/提示词Prompt激发AI绘画的无限创意!

你有没有想过用AI来画画&#xff1f;ChatGPT是一款基于GPT-3的聊天模式的AI绘画工具&#xff0c;它可以根据你输入的关键词/咒语/提示词Prompt来生成不同风格和主题的画作。Prompt是一些简短的文字&#xff0c;可以用来指导ChatGPT的创作过程。在这篇文章中&#xff0c;我将展示…

2个月快速通过PMP证书的经验分享

01 PMP证书是什么&#xff1f; 指的是项目管理专业人士资格认证。它是由美国项目管理协会&#xff08;Project Management Institute(简称PMI)&#xff09;发起的&#xff0c;严格评估项目管理人员知识技能是否具有高品质的资格认证考试。其目的是为了给项目管理人员提供统一的…

Redis【性能 02】Redis-5.0.14伪集群和Docker集群搭建及延迟和性能测试(均无法提升性能)

伪集群及Docker集群搭建测试流程 1.伪集群搭建1.1 环境1.2 搭建1.2.1 集群配置1.2.2 生成其他5个节点配置1.2.3 启动并验证节点状态1.2.4 创建集群1.2.5 集群信息 1.3 测试 2.Docker集群2.1 环境2.2 搭建2.2.1 创建专用网络2.2.2 生成配置文件2.2.3 容器启动及验证2.2.4 创建集…

NIST SP 800-193: BIOS 平台固件弹性指南

NIST SP 800-147&#xff0c;BIOS 保护指南 ( NIST SP 800-147 [1]、NIST SP 800-147B [2]&#xff09;解决了 BIOS 的保护问题 可从此处免费获得&#xff1a; https://doi.org/10.6028/NIST.SP.800-193 摘要 此文档提供了关于支持平台固件和数据对抗潜在地具有破坏性的攻…

python的 __init__.py文件中使用__all__变量

在Python的包&#xff08;Package&#xff09;中&#xff0c;init.py文件可以被用作初始化包的脚本。这个文件会在包被导入时自动执行。同时&#xff0c;init.py文件中的__all__变量也可以被用来限制包中可导入的模块、类或方法。具体来说&#xff0c;__all__变量应该是一个列表…

项目上线 | 兰精携手盖雅工场,数智驱动绿色转型

近年来&#xff0c;纺织纤维行业零碳行动如火如荼。作为低碳环保消费新时尚引领者&#xff0c;同时也是纤维领域隐形冠军&#xff0c;兰精在推进绿色发展的同时&#xff0c;也在不断向内探索企业数字化转型之道&#xff0c;以此反哺业务快速扩张。 数智转型&#xff0c;管理先…

计算机网络面试题(上)

1.TCP/IP 网络模型有哪几层&#xff1f; TCP/IP 网络通常是由上到下分成 4 层&#xff0c;分别是应用层&#xff0c;传输层&#xff0c;网络层和网络接口层。 每一层的封装格式&#xff1a; 网络接口层的传输单位是帧&#xff08;frame&#xff09;&#xff0c;IP 层的传输单位…