利用 Valgrind 检测 C++ 内存泄露
Valgrind 是一款运行在 Linux 系统上的编程工具集,主要用于调试和分析程序的性能、内存使用等问题。其中最常用的工具是 Memcheck,它可以帮助检测 C 和 C++ 程序中的内存管理错误,如内存泄漏、使用未初始化的内存、越界访问等。
安装
这里我以Ubuntu 22.04(WSL)为例子,安装很简单:
sudo apt-get install valgrind
bluebonnet27@bluebonnet27:~/Project/CPP$ valgrind --version
valgrind-3.18.1
使用
编写包含潜在内存泄露问题的 C++ 代码
以下是一个简单的 C++ 程序示例,其中存在内存泄露问题
#include <iostream>int main() {int* ptr = new int[10];// 没有释放分配的内存return 0;
}
在这个程序中,我们使用new操作符分配了一个包含 10 个整数的数组,但没有使用delete[]来释放这块内存,从而导致了内存泄露。
编译程序
使用g++编译器编译程序,并确保开启调试信息(使用-g选项),这样 Valgrind 在检测到问题时可以提供更详细的错误信息:
g++ -g -o memLeak memLeak.cpp
使用 Valgrind 运行程序
使用 Valgrind 的 Memcheck 工具来运行编译好的程序:
valgrind --leak-check=full --show-leak-kinds=all ./memLeak
分析 Valgrind 的输出结果
运行上述命令后,Valgrind 会输出详细的内存使用信息和检测到的问题
==36044== Memcheck, a memory error detector
==36044== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==36044== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==36044== Command: ./memLeak
==36044==
==36044==
==36044== HEAP SUMMARY:
==36044== in use at exit: 40 bytes in 1 blocks
==36044== total heap usage: 2 allocs, 1 frees, 72,744 bytes allocated
==36044==
==36044== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==36044== at 0x484A2F3: operator new[](unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==36044== by 0x10919E: main (memLeak.cpp:4)
==36044==
==36044== LEAK SUMMARY:
==36044== definitely lost: 40 bytes in 1 blocks
==36044== indirectly lost: 0 bytes in 0 blocks
==36044== possibly lost: 0 bytes in 0 blocks
==36044== still reachable: 0 bytes in 0 blocks
==36044== suppressed: 0 bytes in 0 blocks
==36044==
==36044== For lists of detected and suppressed errors, rerun with: -s
==36044== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
从输出中可以看到,definitely lost: 40 bytes in 1 blocks 表示确定存在 40 字节的内存泄露,并且指出泄露发生在 memLeak.cpp 文件的第 4 行,这正是我们使用new分配内存但没有释放的地方。
修复内存泄露问题
根据 Valgrind 的输出信息,修改代码来释放分配的内存:
#include <iostream>int main() {int* ptr = new int[10];// 释放分配的内存delete[] ptr;return 0;
}
重新编译并使用 Valgrind 运行修改后的程序
==36689== Memcheck, a memory error detector
==36689== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==36689== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==36689== Command: ./memLeak
==36689==
==36689==
==36689== HEAP SUMMARY:
==36689== in use at exit: 0 bytes in 0 blocks
==36689== total heap usage: 2 allocs, 2 frees, 72,744 bytes allocated
==36689==
==36689== All heap blocks were freed -- no leaks are possible
==36689==
==36689== For lists of detected and suppressed errors, rerun with: -s
==36689== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
此时不再有内存泄漏。
valgrind的局限性
下面的代码也存在内存泄漏,因为使用基类指针指向派生类对象,并且基类的析构函数不是虚函数时,通过基类指针删除对象可能不会调用派生类的析构函数,从而导致派生类部分的内存没有被正确释放。
#include <iostream>class Base {
public:Base() { std::cout << "Base constructor" << std::endl; }~Base() { std::cout << "Base destructor" << std::endl; }
};class Derived : public Base {
public:Derived() { std::cout << "Derived constructor" << std::endl; }~Derived() { std::cout << "Derived destructor" << std::endl; }
};void memoryLeak4() {Base* ptr = new Derived();delete ptr; // 只会调用基类的析构函数,派生类部分内存未释放
}int main() {memoryLeak4();return 0;
}
但这样的代码并不能被valgrind检测出内存泄漏,因为 Valgrind 主要基于内存分配和释放操作来判断是否有泄漏,而这种情况下内存的释放操作确实执行了(基类部分的内存被释放),只是派生类部分的析构函数没有被调用,没有从表面上体现出 “未释放” 的特征。
我们修改下代码,让Derived 类的构造函数里使用 new[] 分配了一个包含 10 个 int 元素的数组,而析构函数中使用 delete[] 来释放这块内存。当使用基类指针 Base* ptr = new Derived(); 创建派生类对象,并且基类析构函数不是虚函数时,执行 delete ptr; 只会调用基类的析构函数,派生类的析构函数不会被调用,这就导致 data 所指向的内存没有被释放。
#include <iostream>class Base {
public:Base() { std::cout << "Base constructor" << std::endl; }~Base() { std::cout << "Base destructor" << std::endl; }
};class Derived : public Base {
private:int* data;
public:Derived() {std::cout << "Derived constructor" << std::endl;data = new int[10]; // 派生类中动态分配内存}~Derived() {std::cout << "Derived destructor" << std::endl;delete[] data; // 释放派生类中分配的内存}
};void memoryLeak4() {Base* ptr = new Derived();delete ptr; // 只会调用基类的析构函数,派生类部分内存未释放
}int main() {memoryLeak4();return 0;
}
此时 Valgrind 就能检测到内存泄漏了,并正确打印了内存泄漏的代码行:
==37900== Memcheck, a memory error detector
==37900== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==37900== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==37900== Command: ./memLeak
==37900==
Base constructor
Derived constructor
Base destructor
==37900==
==37900== HEAP SUMMARY:
==37900== in use at exit: 40 bytes in 1 blocks
==37900== total heap usage: 4 allocs, 3 frees, 73,776 bytes allocated
==37900==
==37900== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==37900== at 0x484A2F3: operator new[](unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==37900== by 0x1093EB: Derived::Derived() (memLeak.cpp:15)
==37900== by 0x10924C: memoryLeak4() (memLeak.cpp:24)
==37900== by 0x1092A6: main (memLeak.cpp:29)
==37900==
==37900== LEAK SUMMARY:
==37900== definitely lost: 40 bytes in 1 blocks
==37900== indirectly lost: 0 bytes in 0 blocks
==37900== possibly lost: 0 bytes in 0 blocks
==37900== still reachable: 0 bytes in 0 blocks
==37900== suppressed: 0 bytes in 0 blocks
==37900==
==37900== For lists of detected and suppressed errors, rerun with: -s
==37900== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
相关文章:
利用 Valgrind 检测 C++ 内存泄露
Valgrind 是一款运行在 Linux 系统上的编程工具集,主要用于调试和分析程序的性能、内存使用等问题。其中最常用的工具是 Memcheck,它可以帮助检测 C 和 C 程序中的内存管理错误,如内存泄漏、使用未初始化的内存、越界访问等。 安装 这里我以…...
Python中的HTTP客户端库:httpx与request | python小知识
Python中的HTTP客户端库:httpx与request | python小知识 在Python中,发送HTTP请求和处理响应是网络编程的基础。requests和httpx是两个常用的HTTP库,它们都提供了简洁易用的API来发送HTTP请求。然而,httpx作为新一代的HTTP客户端…...
【Python】Python入门基础——环境搭建
学习Python,首先需要搭建一个本地开发环境,或是使用线上开发环境(各类练习网站),这里主要记录本地开发环境的配置。 目录: 一、下载和安装python解释器 官网下载地址:Download Python | Pytho…...
2025 pwn_A_childs_dream
文章目录 fc/sfc mesen下载和使用推荐 fc/sfc https://www.mesen.ca/docs/ mesen2安装,vscode安装zg 任天堂yyds w d 左右移动 u结束游戏 i崩溃或者卡死了 L暂停 D658地方有个flag 发现DEEE会使用他。且只有这个地方,maybe会输出flag,应…...
面试题整理:操作系统
文章目录 操作系统操作系统基础1. 操作系统的功能?2. 什么是用户态和内核态? 进程和线程1. 是什么?区别?2. ⭐线程间的同步的方式有哪些?3. PCB 是什么?包含哪些信息?4. 进程的状态有哪些&#…...
构建未来教育的基石:智慧校园与信息的重要性
随着科技的迅猛发展,教育领域正经历一场深刻的变革。在这个过程中,“智慧校园”作为教育信息化的重要实践,扮演着不可或缺的角色。智慧校园不仅仅是硬件设施的升级,更是一种全新的教育理念,强调利用信息技术优化教育资…...
C# 控制台相关 API 与随机数API
C# 控制台相关 API 与随机数API 控制台输入输出 功能说明 Console.WriteLine(string): 输出字符串并换行Console.Write(string, string): 输出字符串不换行Console.ReadLine(): 等待用户输入并返回字符串Console.ReadKey(bool).KeyChar: 读取按键,指定是否显示输…...
【踩坑】⭐️MyBatis的Mapper接口中不建议使用重载方法
目录 🍸前言 🍻一、背景 🍹二、问题处理 💞️三、处理方法 🍸前言 小伙伴们大家好,很久没有水..不是,写文章了,都收到系统的消息了;我算下时间,上周是单休…...
CSS Grid 网格布局,以及 Flexbox 弹性盒布局模型,它们的适用场景是什么?
CSS Grid网格布局和Flexbox弹性盒布局模型都是现代CSS布局的重要工具,它们各自具有独特的优势和适用场景。 作为前端开发工程师,理解这些布局模型的差异和适用场景对于编写高效、可维护的代码至关重要。 CSS Grid网格布局 适用场景: 复杂…...
HDFS体系结构
HDFS 支持主从结 构 , 主节 点 称为 NameNode ,从节点称为 DataNode HDFS中还包含一个 SecondaryNameNode 进程,只要辅助主节点 公司BOSS:NameNode (NN) 秘书:SecondaryNameNode (2NN) 员工&a…...
AI大模型的技术突破与传媒行业变革
性能与成本:AI大模型的“双轮驱动” 过去几年,AI大模型的发展经历了从实验室到产业化的关键转折。2025年初,以DeepSeek R1为代表的模型在数学推理、代码生成等任务中表现超越国际头部产品,而训练成本仅为传统模型的几十分之一。这…...
vscode/cursor+godot C#中使用socketIO
在 Visual Studio Code(VS Code)中安装 NuGet 包(例如SocketIOClient),你可以通过以下几种方法: 方法 1:使用dotnet cli 打开终端:在 VS Code 中按下Ctrl 或者通过菜单View -> Terminal打开终端。 导…...
分段线性插值
分段线性插值 分段线性插值,就是将插值点用折线段连接起来逼近f(x)。设已知节点 a x 0 < x 1 < ⋅ ⋅ ⋅ < x n b ax_0<x_1<<x_nb ax0<x1<⋅⋅⋅<xnb上的函数值 f 0 , f 1 , . . . , f n f_0,f_1,...,f_n f0,f1,...,fn&a…...
制作一个项目用于研究elementUI的源码
需求:修改el-tooltip的颜色,发现传递参数等方法都不太好用,也可以使用打断点的方式,但也有点麻烦,因此打算直接修改源码,把组件逻辑给修改了 第一步下载源码 源码地址 GitHub - ElemeFE/element: A Vue.j…...
[AI]从零开始的llama.cpp部署与DeepSeek格式转换、量化、运行教程
一、前言 在上一次的DeepSeek的部署教程中,我们使用Ollama与LM Studio很轻松的部署了DeepSeek并且也完成了相关API的调用,如果还有不会的小伙伴请看下面的教程: DeepSeek本地部署:[AI]从零开始的DeepSeek本地部署及本地API调用教…...
vLLM专题(二):安装-CPU
vLLM 是一个 Python 库,支持以下 CPU 变体。选择您的 CPU 类型以查看供应商特定的说明: Intel/AMD x86 vLLM 最初支持在 x86 CPU 平台上进行基本模型推理和服务,支持的数据类型包括 FP32、FP16 和 BF16。 注意 此设备没有预构建的 wheel 包或镜像,因此您必须从源代码构建 v…...
JVM 底层探秘:对象创建的详细流程、内存分配机制解析以及线程安全保障策略
文章目录 1. 类加载检查2. 内存分配① 指针碰撞② 空闲列表线程安全问题: 3. 内存空间初始化4. 对象头设置5. 对象初始化 当Java虚拟机遇到一条 new指令时,会执行以下步骤来创建对象: 1. 类加载检查 首先检查new指令的参数是否能在常量池中…...
【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-Chapter14-DOM
十四、DOM 文档对象模型(DOM,Document Object Model)是 HTML 和 XML 文档的编程接口。DOM 表示由多层节点构成的文档,通过它开发者可以添加、删除和修改页面的各个部分。脱胎于网景和微软早期的动态 HTML(DHTML&#x…...
外汇掉期(FX Swap):全球企业管理外汇风险的关键工具(中英双语)
外汇掉期(FX Swap):全球企业管理外汇风险的关键工具 引言 在全球化经济环境下,跨国公司、银行和金融机构经常面临外汇风险,因为它们的业务涉及多种货币。例如,一家中国公司可能需要欧元支付欧洲供应商&am…...
verilog程序设计及SystemVerilog验证
1.Verilog测试程序设计基础 1.1Testbench及其结构 在仿真的时候Testbench用来产生测试激励给待验证设计( Design Under Verification, DUV),或者称为待测设计(Design UnderTest, DUT) 。 测试程序的一般结构: Testbench是一个测试平台,信号…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...
【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...
