0

0

C++内存泄漏怎么检测 C++内存管理与智能指针使用指南【避坑】

冰火之心

冰火之心

发布时间:2026-02-03 15:33:20

|

199人浏览过

|

来源于php中文网

原创

Valgrind仅捕获进程退出时未释放的堆内存泄漏;报告为空常因程序未正常退出、符号缺失或泄漏发生在共享库中。

c++内存泄漏怎么检测 c++内存管理与智能指针使用指南【避坑】

Valgrind 能抓到哪些内存泄漏,为什么有时报告为空

Valgrind 的 memcheck 是 Linux 下最可靠的运行时检测工具,但它只捕获进程退出时仍被持有的堆内存(即未调用 freedeletemalloc/new 分配)。如果程序长期运行、未退出,或泄漏发生在共享库内部且未正确导出符号,valgrind --leak-check=full 可能显示 “no leaks are possible” 或漏报。

实操建议:

立即学习C++免费学习笔记(深入)”;

  • 务必在程序正常退出后检查报告,避免用 kill -9 终止进程
  • 编译时加 -g 且禁用优化(-O0),否则行号和调用不可读
  • 对 C++ 类,确认析构函数是否被调用——若对象被 std::shared_ptr 循环引用,valgrind 仍会报告“still reachable”,而非“definitely lost”
  • 注意 std::stringstd::vector 等容器内部的堆分配也会被追踪,但它们本身不构成泄漏(只要对象生命周期结束)

std::unique_ptr 和 std::shared_ptr 哪里容易误用导致泄漏

std::unique_ptr 本身几乎不会造成泄漏,问题多出在“本该用它却用了裸指针”,或跨线程传递后忘记 std::move。而 std::shared_ptr 的泄漏主因是循环引用:A 持有 B 的 shared_ptr,B 也持有 A 的 shared_ptr,两者引用计数永远 >0。

实操建议:

立即学习C++免费学习笔记(深入)”;

  • 优先用 std::unique_ptr 表达独占所有权;仅当明确需要共享语义时才升级为 std::shared_ptr
  • 打破循环引用必须用 std::weak_ptr 替换其中一端(通常是观察者、回调上下文等非拥有方)
  • 避免从 this 直接构造 shared_ptr(如 std::shared_ptr(this)),应继承 std::enable_shared_from_this 并用 shared_from_this()
  • 注意 std::make_sharedstd::shared_ptr(new T) 更高效且异常安全,但无法自定义删除器——需删除器时改用后者

Windows 下用 Visual Studio 检测内存泄漏要开哪些设置

MSVC 自带的 CRT 调试堆只对 _CrtDumpMemoryLeaks() 调用时刻的堆快照负责,它默认不追踪 C++ new,除非你重载了全局 operator new 并接入 CRT 勾子。常见错误是只在 main 结尾调用,却忽略了静态对象析构可能释放内存的时间差。

Dora
Dora

创建令人惊叹的3D动画网站,无需编写一行代码。

下载

实操建议:

立即学习C++免费学习笔记(深入)”;

  • #include 后,于 main 开头加:_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  • 确保泄漏报告出现在控制台输出中——若用 GUI 项目或子系统为 Windows,需手动重定向 stdout(或改用 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG)
  • 配合 _CrtSetBreakAlloc(1234) 在第 1234 次分配时中断,定位具体泄漏点(需从泄漏报告中看 “{1234}” 编号)
  • 不要依赖 IDE 的“诊断工具→内存使用”实时图——它采样间隔大,且不显示未释放的 small object(如短字符串缓冲区)

为什么 RAII 正确了还会有泄漏:静态变量与初始化顺序陷阱

即使所有类都遵守 RAII,静态对象之间的初始化顺序未定义,可能导致某个静态 std::shared_ptr 析构时,它所指向的对象(另一个静态对象)已被销毁,进而触发未定义行为或资源未清理。更隐蔽的是,DLL 中的静态智能指针在进程卸载时可能来不及析构。

实操建议:

立即学习C++免费学习笔记(深入)”;

  • 避免在不同编译单元的静态变量之间建立强依赖(尤其是跨 DLL)
  • 用局部静态变量 + 函数返回引用替代全局对象(即 Meyer 单例),确保首次访问才构造、且析构顺序可控
  • 对必须跨模块共享的资源,改用工厂函数 + 显式 init()/shutdown() 生命周期管理,而非依赖静态析构
  • Clang/GCC 下可加 __attribute__((init_priority(N))) 控制初始化顺序(N 越小越早),但 MSVC 不支持,慎用

真正难排查的泄漏往往不在 new/delete 配对错误,而在对象图的生命周期设计——比如一个 shared_ptr 被塞进全局容器却忘了清除,或者异步回调捕获了 this 但任务队列永不执行。这类问题靠工具只能提示“still reachable”,最终得靠代码审查+生命周期建模。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

543

2023.08.02

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

361

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

213

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1505

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

626

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

718

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

670

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

175

2025.07.29

全国统一发票查询平台入口合集
全国统一发票查询平台入口合集

本专题整合了全国统一发票查询入口地址合集,阅读专题下面的文章了解更多详细入口。

4

2026.02.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 8.4万人学习

Git 教程
Git 教程

共21课时 | 3.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号