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

这篇具有很好参考价值的文章主要介绍了聊一聊 Valgrind 监视非托管内存泄露和崩溃。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一:背景

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 以仿真的方式把程序跑起来,截图如下:

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

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

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

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;
}

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

从图中可以清晰的看到,主线程栈上的地址 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 的栈空间,截图如下:

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

虽然 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 在洞察内存方面还是非常强大的,但也有它不能触及到的地方,熟悉它的优点和缺点,全面了解对我们调试师来说至关重要,希望本篇对你有帮助。文章来源地址https://www.toymoban.com/news/detail-434235.html

到了这里,关于聊一聊 Valgrind 监视非托管内存泄露和崩溃的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 聊一聊大模型

    事情还得从ChatGPT说起。 2022年12月OpenAI发布了自然语言生成模型ChatGPT,一个可以基于用户输入文本自动生成回答的人工智能体。它有着赶超人类的自然对话程度以及逆天的学识。一时间引爆了整个人工智能界,各大巨头也纷纷跟进发布了自家的大模型,如:百度-文心一言、科

    2024年02月05日
    浏览(58)
  • 聊一聊synchronized

    在 Java 中, synchronized 可以用于实现线程同步,有以下几种常见的使用方式: 修饰代码块:将 synchronized 放在代码块的前面, 例如: 在这种方式下,会为给定的对象 obj 获取锁,在代码块执行期间,只有持有该锁的线程才能进入代码块执行。 修饰方法:将 sync

    2024年01月22日
    浏览(63)
  • 聊一聊模板方法模式

    统一抽取,制定规范; 模板方法模式,又叫模板模式,属于23种设计模式中的 行为型模式 。在抽象类中公开定义了执行的方法,子类可以按需重写其方法,但是要以抽象类中定义的方式调用方法。总结起来就是: 定义一个操作的算法结构,而将一些步骤延迟到子类中。在不

    2024年02月04日
    浏览(57)
  • 聊一聊Vue和Ts

    1 前言 Vue3 已经正式发布了一段时间了,各种生态已经成熟。最近使用 taro+vue3 重构冷链的小程序,经过了一段时间的开发和使用,有了一些自己的思考。 总的来说,Vue3 无论是在底层原理还是在实际开发过程中,都有了很大的进步。 从源码层面来说,使用 Proxy 代替 Object.d

    2023年04月08日
    浏览(74)
  • 聊一聊适配器模式

    接口不能用?行,我帮你适配 适配器模式(Adapter),是23种设计模式中的 结构型模式 之一;它就像我们电脑上接口不够时,需要用到的拓展坞,起到转接的作用。它可以将新的功能和原先的功能连接起来,使由于需求变动导致不能用的功能,重新利用起来。 上图的Mac上,只

    2024年02月04日
    浏览(54)
  • 聊一聊mysql中的间隙锁

    间隙锁在mysql中经常使用到,今天就聊一聊mysql的间隙锁的内容。 间隙锁是为了解决幻读的问题,并且在当前读的场景下解决的。 当前读包含:update,delete,insert,select…lock in share mode,select…for update 一基本概念 1、行锁:给某一行进行加锁 2、间隙锁:两个值之间的间隙,为解

    2024年02月12日
    浏览(45)
  • 聊一聊Java抽象同步队列AQS

    AQS是锁的底层支持 由该图可以看到,AQS是一个FIFO的双向队列,其内部通过节点head和tail记录队首和队尾元素,队列元素的类型为Node。其中Node中的thread变量用来存放进入AQS队列里面的线程;Node节点内部的SHARED用来标记该线程是获取共享资源时被阻塞挂起后放入AQS队列的,EX

    2024年02月16日
    浏览(48)
  • 聊一聊nginx中KeepAlive的设置

    之前工作中遇到一个KeepAlive的问题,现在把它记录下来,场景是这样的: 从上图可以看出,用户通过Client访问的是LVS的VIP, VIP后端挂载的RealServer是Nginx服务器。 Client可以是浏览器也可以是一个客户端程序。一般情况下, 这种架构不会出现问题,但是如果Client端把请求发送给

    2024年02月01日
    浏览(63)
  • 聊一聊医疗器械的可用性

    很抱歉由于各种因素这个号拖更了好久了,最近呢也有几个公众号做的挺好的,比如包总的 MD SRE 、丁总的 医械安全 、 饽饽糕的叨逼叨 ,而且更新也都比较频繁,大家可以 关注 一下; 好久没登录,当我上来看到已经有 5000多 的关注者,说实话,有 感动 ,有 自豪 ,也有

    2024年02月07日
    浏览(46)
  • 聊一聊.NET的网页抓取和编码转换

    在本文中,你会了解到两种用于 HTML 解析的类库。另外,我们将讨论关于网页抓取,编码转换和压缩处理的知识,以及如何在 .NET 中实现它们,最后进行优化和改进。 有了 Copilot 的加持,可以让我们快速的完成开发任务,并在极短的时间内完成小工具的开发。谁能想到现如今

    2024年02月12日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包