c/c++内存泄露的检测方法
此文内容摘自
https://zhuanlan.zhihu.com/p/22664202
作为 从零开始的 JSON 库教程(三):解析字符串解答篇 的笔记
1A. Windows 下的内存泄漏检测方法
在 Windows 下,可使用 Visual C++ 的 C Runtime Library(CRT) 检测内存泄漏。
首先,我们在两个 .c 文件首行插入这一段代码:
#ifdef _WINDOWS
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
并在 main() 开始位置插入:
int main() {
#ifdef _WINDOWS
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
在 Debug 配置下按 F5 生成、开始调试程序,没有任何异样。
然后,我们删去 lept_set_boolean() 中的 lept_free(v):
void lept_set_boolean(lept_value* v, int b) {
/* lept_free(v); */
v->type = b ? LEPT_TRUE : LEPT_FALSE;
}
再次按 F5 生成、开始调试程序,在输出会看到内存泄漏信息:
Detected memory leaks!
Dumping objects ->
C:\GitHub\json-tutorial\tutorial03_answer\leptjson.c(212) : {79} normal block at 0x013D9868, 2 bytes long.
Data: <a > 61 00
Object dump complete.
这正是我们在单元测试中,先设置字符串,然后设布尔值时没释放字符串所分配的内存。比较麻烦的是,它没有显示调用堆栈。从输出信息中 ... {79} ... 我们知道是第 79 次分配的内存做成问题,我们可以加上 _CrtSetBreakAlloc(79); 来调试,那么它便会在第 79 次时中断于分配调用的位置,那时候就能从调用堆栈去找出来龙去脉。
1B. Linux/OSX 下的内存泄漏检测方法
在 Linux、OS X 下,我们可以使用 valgrind 工具(用 apt-get install valgrind、 brew install valgrind)。我们完全不用修改代码,只要在命令行执行:
$ valgrind --leak-check=full ./leptjson_test
==22078== Memcheck, a memory error detector
==22078== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==22078== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==22078== Command: ./leptjson_test
==22078==
--22078-- run: /usr/bin/dsymutil "./leptjson_test"
160/160 (100.00%) passed
==22078==
==22078== HEAP SUMMARY:
==22078== in use at exit: 27,728 bytes in 209 blocks
==22078== total heap usage: 301 allocs, 92 frees, 34,966 bytes allocated
==22078==
==22078== 2 bytes in 1 blocks are definitely lost in loss record 1 of 79
==22078== at 0x100012EBB: malloc (in /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==22078== by 0x100008F36: lept_set_string (leptjson.c:208)
==22078== by 0x100008415: test_access_boolean (test.c:187)
==22078== by 0x100001849: test_parse (test.c:229)
==22078== by 0x1000017A3: main (test.c:235)
==22078==
...
它发现了在 test_access_boolean() 中,由 lept_set_string() 分配的 2 个字节("a")泄漏了。
Valgrind 还有很多功能,例如可以发现未初始化变量。我们若在应用程序或测试程序中,忘了调用 lept_init(&v),那么v.type 的值没被初始化,其值是不确定的(indeterministic),一些函数如果读取那个值就会出现问题:
static void test_access_boolean() {
lept_value v;
/* lept_init(&v); */
lept_set_string(&v, "a", 1);
...
}
这种错误有时候测试时能正确运行(刚好 v.type 被设为 0),使我们误以为程序正确,而在发布后一些机器上却可能崩溃。这种误以为正确的假像是很危险的,我们可利用 valgrind 能自动测出来:
$ valgrind --leak-check=full ./leptjson_test
...
==22174== Conditional jump or move depends on uninitialised value(s)
==22174== at 0x100008B5D: lept_free (leptjson.c:164)
==22174== by 0x100008F26: lept_set_string (leptjson.c:207)
==22174== by 0x1000083FE: test_access_boolean (test.c:187)
==22174== by 0x100001839: test_parse (test.c:229)
==22174== by 0x100001793: main (test.c:235)
==22174==
它发现 lept_free() 中依靠了一个未初始化的值来跳转,就是 v.type,而错误是沿自 test_access_boolean()。
编写单元测试时,应考虑哪些执行次序会有机会出错,例如内存相关的错误。然后我们可以利用 TDD 的步骤,先令测试失败(以内存工具检测),修正代码,再确认测试是否成功。
c/c++内存泄露的检测方法的更多相关文章
- C++中内存泄漏的检测方法介绍
C++中内存泄漏的检测方法介绍 首先我们需要知道程序有没有内存泄露,然后定位到底是哪行代码出现内存泄露了,这样才能将其修复. 最简单的方法当然是借助于专业的检测工具,比较有名如BoundsCheck, ...
- 分享.net常见的内存泄露及解决方法
分享.net常见的内存泄露及解决方法 关于内存泄漏的问题,之前也为大家介绍过,比如:<C++中内存泄漏的检测方法介绍>,是关于C++内存泄漏的.今天为大家介绍的是关于.NET内存泄漏的问题 ...
- CPP-基础:内存泄露及其检测工具
[转]浅谈C/C++内存泄露及其检测工具 对于一个c/c++程序员来说,内存泄漏是一个常见的也是令人头疼的问题.已经有许多技术被研究出来以应对这个问题,比如 Smart Pointer,Garba ...
- [转]浅谈C/C++内存泄露及其检测工具
转自:http://www.cnblogs.com/taoxu0903/archive/2007/10/27/939261.html 对于一个c/c++程序员来说,内存泄漏是一个常见的也是令人头疼的问 ...
- C/C++内存泄露及检测工具
内存泄漏的定义 一般我们常说的内存泄漏是指堆内存的泄漏.堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显示释放的内 存.应用程序一般使用malloc,re ...
- VC++ 内存泄露与检测的一种方法
本文介绍,当VC++或者MFC程序,出现内存泄露时,如何快速定位的方法,这种方法有一定的局限性,在注意事项中会给出的. MFC程序 当MFC程序出现内存泄露时,退出程序时的VS调试输出 ...
- Windows系统中内存泄露与检测工具及方法
1.检测需要使用的工具:windbg工具.检测前,需要先安装windbg工具.安装了该工具后,会在安装目录下有一个umdh工具.假设windbg安装在以下目录下:D:\Program Files\De ...
- C++中内存泄露的检测
C++没有java的内存垃圾回收机制,在程序短的时候可能比较容易发现问题,在程序长的时候是否有什么检测的方法呢? 假设有一个函数可以某点检测程序的内存使用情况,那是否可以在程序开始的时候设置一个点,在 ...
- Android内存泄露自动检测神器LeakCanary
经典的面试题: a.怎样在coding过程中避免内存泄露? b.怎样检测内存泄露? 这两个问题我想大部分Android 职位面试时都会被问到吧. 怎样避免就不赘述了,网上很多答案. 工具呢,当然也有很 ...
随机推荐
- asterisk-java ami2 事件监听
asteriskServer文章1提到啦怎么获取,就不解释 asteriskServer.addChainListener(new AsteriskeventListenerInit());//整个服 ...
- JAVA-Web04
1 理解dom解析器机制 1)dom解析和dom4j原理一致 2)Node是所有元素的父接口 3)常用的API: DocumentBuilderFactory factory = Docu ...
- 【Python图像特征的音乐序列生成】一个更科学的图片分类参考方法,以及一个看起来很好用的数据集
数据集地址:http://www.imageemotion.org/ 论文地址:http://www.doc88.com/p-1905670442096.html
- 查看nvidia的GPU
nvidia-smi就可以查看,可以看到进程的占用率,可以kill杀掉进程 注意这里的-前后都不要空格,连起来写
- Python列表解析与生成器表达式
Python列表解析 l = ["egg%s" %i for i in range(100) if i > 50] print(l) l= [1,2,3,4] s = 'he ...
- JavaScript -- 内置对象数组
数组 创建数组的基本方式有两种: 1.使用 Array构造函数 语法:new Array() 小括号( )说明: (1)预先知道数组要保存的项目数量 (2)向Array构造函数中传递数组应包含的项 2 ...
- jquery源码学习第一天
第一天认识了jquery的大体结构,总的大范围是 (function() { // 这里是封装的代码,包括了各种方法.工具 window.JQuery = JQuery window.$ = $; } ...
- MySQL左右连接查询中的NULL的数据筛选问题
这里使用左连接为例子,对于左连接是将左边表的数据显示,右边表中如果没有对应的数据则使用null填充. game表: game_type表: SELECT g.name,g.type_id,t.type ...
- Docker自学纪实(一)Docker介绍
先简单了解一下,做个记录,以便不时之需. Docker简介:Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依 ...
- Unity基础-编辑器
编辑器 Special Folders Hidden Folder(start with .) Standard Assets:第一批加载的文件 Editor:只在编辑下才能使用, Plugins R ...