C/C++内存检测工具valgrind--memcheck
Valgrind简介
Valgrind是运行在Linux上的一套基于仿真技术的程序调试和分析工具,作者是获得过Google-O’Reilly开源大奖的Julian Seward,它包含一个内核 —— 一个软件合成的CPU,和一系列的小工具,每个工具都可以完成一项任务──调试,分析,或测试等,内存检测,我们可以使用它的工具:Memcheck。
Valgrind安装
方法 1. valgrind官网:http://valgrind.org下载
方法 2. Ubuntu: sudo apt-get install valgrind
Memcheck的检测范围
它可以用来检测c/c++程序中出现的内存问题,所有对内存的读写都会被检测到,一切对malloc()/free()/new/delete的调用都会被捕获。所以,它能检测以下问题:
1). 对未初始化内存的使用;
2). 读/写释放后的内存块;
3). 读/写超出malloc等分配的动态内存范围;
4). 读/写不适当的栈中内存块;
5). 内存泄漏,指向一块内存的指针永远丢失;
6). 不正确的malloc/free或new/delete匹配;
7). memcpy()相关函数中的dst和src指针重叠问题。
Memcheck检测使用步骤及注意事项
1、在编译程序的时候打开调试模式(gcc编译器的-g选项),以便显示行号,编译时去掉-O1 -O2等优化选项;检查的是C++程序的时候,考虑加上选项: -fno- inline ,这样它函数调用链会很清晰。
2、执行:valgrind --tool=memcheck --leak-check=full --log-file=./log.txt ./YourProgram
3、程序运行结束,查看 log.txt 中的结果。
结果分析:
Valgrind(memcheck)包含这7类错误,黑体为一般的错误提示:
1、illegal read/illegal write errors 非法读取/非法写入错误
2、use of uninitialised values 使用未初始化的区域
3、use of uninitialised or unaddressable values in system calls 系统调用时使用了未初始化或不可寻址的地址
4、illegal frees 非法的释放
5、when a heap block is freed with an inappropriate deallocation function 分配和释放函数不匹配
6、overlapping source and destination blocks 源和目的内存块重叠
7、memory leak detection 内存泄漏检测
7.1 Still reachable 内存指针还在还有机会使用或者释放,指针指向的动态内存还没有被释放就退出了
7.2 Definitely lost 确定的内存泄露,已经不能够访问这块内存
7.3 Indirectly lost 指向该内存的指针都位于内存泄露处
7.4 Possibly lost 可能的内存泄露,仍然存在某个指针能够访问某块内存,但该指针指向的已经不是该内存首位置
7.5 Suppressed 某些库产生的错误不予以提示,这些错误会被统计到suppressed项目
测试案例:
最近刚刚用最小堆实现了一个定时容器,写完之后就使用Valgrind的memcheck工具检测了一些内存,log日志如下:
==38716== Memcheck, a memory error detector
==38716== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==38716== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==38716== Command: ./test_heap_timer_new
==38716== Parent PID: 17817
==38716==
==38716== Invalid write of size 4
==38716== at 0x10BFF8: HeapTimer<Event>::setPos(int) (heap_timer.hpp:59)
==38716== by 0x10BF30: HeapTimerContainer<Event>::percolateDown(int) (heap_timer.hpp:334)
==38716== by 0x10BAD3: HeapTimerContainer<Event>::popTimer() (heap_timer.hpp:300)
==38716== by 0x10B79C: HeapTimerContainer<Event>::tick() (heap_timer.hpp:196)
==38716== by 0x10B34C: main (test_heap_timer_new.cpp:307)
==38716== Address 0x4db2478 is 24 bytes inside a block of size 32 free'd
==38716== at 0x483D1CF: operator delete(void*, unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==38716== by 0x10BA8B: HeapTimerContainer<Event>::popTimer() (heap_timer.hpp:296)
==38716== by 0x10B79C: HeapTimerContainer<Event>::tick() (heap_timer.hpp:196)
==38716== by 0x10B34C: main (test_heap_timer_new.cpp:307)
==38716== Block was alloc'd at
==38716== at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==38716== by 0x10B808: HeapTimerContainer<Event>::addTimer(long) (heap_timer.hpp:212)
==38716== by 0x10AC77: acceptConn(Event*, ITimerContainer<Event>*) (test_heap_timer_new.cpp:175)
==38716== by 0x10B2B5: main (test_heap_timer_new.cpp:293)
==38716==
==38716==
==38716== HEAP SUMMARY:
==38716== in use at exit: 0 bytes in 0 blocks
==38716== total heap usage: 10 allocs, 10 frees, 78,304 bytes allocated
==38716==
==38716== All heap blocks were freed -- no leaks are possible
==38716==
==38716== For lists of detected and suppressed errors, rerun with: -s
==38716== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
可以看到有一个4字节的无效内存写入,是在HeapTimer::setPos(int) (heap_timer.hpp:59)里面,我找了半天,最终发现了原因。
原代码链接:高性能定时器1——最小堆实现_Peerless__的博客-CSDN博客
代码如下:
template <typename _UData>
void HeapTimerContainer<_UData>::tick()
{std::cout << "----------tick----------" << std::endl;HeapTimer<_UData> *tmp = _array[0];time_t cur = getMSec();// 循环处理到期的定时器while(!isEmpty()){if(!tmp){break;}// 如果定时器没到期,则退出循环if(tmp->getExpire() > cur){break;}tmp->handleTimeOut();// 将堆顶元素删除,同时生成新的堆顶定时器popTimer();tmp = _array[0];}
}template <typename _UData>
void HeapTimerContainer<_UData>::popTimer()
{if(isEmpty()){return;}if(_array[0]){delete _array[0];// 将原来的堆顶元素替换为堆数组中最后一个元素_array[0] = _array[--_size];// 对新的堆顶元素执行下滤操作percolateDown(0);}
}// 最小堆的下滤操作,它确保数组中以第hole个节点作为根的子树拥有最小堆性质
template <typename _UData>
void HeapTimerContainer<_UData>::percolateDown(int hole)
{/* if(_size == 0){return;}*/HeapTimer<_UData> *temp = _array[hole];int child = 0;for(; ((hole * 2 + 1) <= _size - 1); hole = child){child = hole * 2 + 1;if((child < (_size - 1)) && (_array[child + 1]->getExpire() < _array[child]->getExpire())){child++;}if(_array[child]->getExpire() < temp->getExpire()){_array[hole] = _array[child];_array[hole]->setPos(hole); // 调整定时器的位置时,重新设置timer中pos保存的其在数组中的位置}else {break;}}_array[hole] = temp;_array[hole]->setPos(hole);
}
上面代码的逻辑是,tick函数被调用就会从最小堆中取出最近要超时的定时器(也就是堆顶元素),检查是否超时,如果超时就执行回调函数,然后调用popTimer弹出堆顶元素。在popTimer中delete掉了刚超时的定时器,并将堆数组中最后一个元素放到堆顶,然后调用percolateDown来调整最小堆。Valgrind生成的日志中提示在HeapTimer::setPos(int) (heap_timer.hpp:59)出错了。后来发现,如果堆中只有一个元素,这段代码_array[0] = _array[–_size];也就变成了_array[0] = _array[0];然后就是在percolateDown函数中对已经delete掉的对象调用了setPos函数。也就是使用了已经delete掉的对象,但是程序运行的时候竟然没有崩溃,这是个挺大的隐患的,没有崩溃更为恐怖,因为可能下一次就要崩溃。解决方案就是在percolateDown函数中加一个数组是否为空的判断,如果为空直接返回就好了。
C/C++内存检测工具valgrind--memcheck相关推荐
- 【调试】Linux下超强内存检测工具Valgrind
[调试]Linux下超强内存检测工具Valgrind 内容简介 Valgrind是什么? Valgrind的使用 Valgrind详细教程 1. Valgrind是什么? Valgrind是一套Lin ...
- 【Linux】内存检测工具Valgrind
内存检测工具Valgrind Valgrind是运行在Linux上的一套基于仿真技术的程序调试和分析工具,作者是获得过Google-O'Reilly开源大奖的Julian Seward,它包含一个内核 ...
- 动态内存检测工具Valgrind
1. Valgrind查找内存泄露利器 Valgrind是一个GPL的软件,用于Linux(For x86, amd64 and ppc32)程序的内存调试和代码剖析.你可以在它的环境中运行你的程序来 ...
- C/C++的内存泄漏检测工具Valgrind memcheck的使用经历
Linux下的Valgrind真是利器啊(不知道Valgrind的请自觉查看参考文献(1)(2)),帮我找出了不少C++中的内存管理错误,前一阵子还在纠结为什么VS 2013下运行良好的程序到了Lin ...
- c linux new使内存耗尽_C/C++的内存泄漏检测工具Valgrind memcheck的使用经历
Linux下的Valgrind真是利器啊(不知道Valgrind的请自觉查看参考文献(1)(2)),帮我找出了不少C++中的内存管理错误,前一阵子还在纠结为什么VS 2013下运行良好的程序到了Lin ...
- linux安装系统内存检测,Ubuntu下安装内存检测工具Valgrind
Ubuntu下安装Valgrind很简单,直接从ubuntu软件中心下载安装,并且还会提供一个简单的图形界面..当然,你也可以在命令行中使用. Valgrind实际上是一个工具集,包含多个调试工具,如 ...
- C/C++内存检测工具valgrind
valgrind是什么 用来检测C/C++程序中出现的内存问题 所有对内存的读写将会被检测 malloc() free() new() delete() 这些函数的调用都会被捕获 相关检测的内容 1. ...
- 内存检测王者之剑—valgrind
记得在大学的刚开始学习C/C++的时候,对于内存问题一点也没有关心过,其实也是关心比较少,知道后来才慢慢注意起来,当时排查是否有内存泄漏全靠手,去看看malloc和free或者new和delete是否 ...
- Ubuntu下内存泄露检测工具Valgrind的使用
在VS中可以用VLD检测是否有内存泄露,可以参考http://blog.csdn.net/fengbingchun/article/details/44195959,下面介绍下Ubuntu中内存泄露检 ...
- Windows和Linux内存检测工具:Valgrind,Visual Leak Detector,CppCheck, Cpplint
1 Linux内存泄漏检测工具Valgrind Valgrind简介 Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合.Valgrind由内核(core)以及基于内核 ...
最新文章
- BusinessObject J2EE单点登陆简单使用
- Hadoop架构-YARN
- 缩进动画Scaleanimation的一个小示例
- To B设计系统 - 在平平淡淡中开花结果
- Flask 系列之 Blueprint
- 【转】Linux中多线程wait使用注意
- UE4学习-在虚幻编辑器中打开VS的三种方式
- webpack打包样式资源_使用loader去打包css文件_打包less文件---webpack工作笔记004
- Java自带的keytool命令
- BlenderPython (三)bpy模块
- 太强了,头发丝完整保留!一个开源的 Python 实时视频抠图工具
- 逻辑漏洞(基本概念、爆破)
- MATLAB生成(对角线上元素相同的)三对角矩阵的实例
- 手机端和PC端开发区别
- eleme 项目使用到的库
- Codeforces ~ 1009C ~ Annoying Present (贪心)
- 软件测试周刊(第86期):一个人为寻求他所需要的东西,走遍了全世界。回到家里,找到了。
- arXiv每日推荐-5.16:语音/音频每日论文速递
- 批量缩小图片大小的方法
- winSCP 集成PuTTY附下载
热门文章
- 用mysql+php开发网上商城系统
- 覆盖常见四大应用场景,华为云CDN能够更好满足企业业务加速需求
- 【高级Java开发】类QQ聊天工具的设计与实现(代码已上传)
- CVPR 2020 | 旷视研究院探究优化场景文字识别的「词汇依赖」问题
- fedora linux搜狗输入法,在Fedora 28系统下安装搜狗输入法
- basic4android计算器,vb三角函数计算器代码
- 使用 VS 2008 编译 ECW SDK 3.3
- requests使用socks代理
- 火车头采集器如何自制php插件
- 1个球从100m落下,每次时,反跳原高度的一半,再落,再反弹,求第10次落地共经过多少m,第10次反弹多高。 谭浩强《c语言程序设计》第五章第十一题