利用 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是一个测试平台,信号…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...
数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)
名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 原创笔记:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:《数据结构第4章 数组和广义表》…...
