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相关推荐

  1. 【调试】Linux下超强内存检测工具Valgrind

    [调试]Linux下超强内存检测工具Valgrind 内容简介 Valgrind是什么? Valgrind的使用 Valgrind详细教程 1. Valgrind是什么? Valgrind是一套Lin ...

  2. 【Linux】内存检测工具Valgrind

    内存检测工具Valgrind Valgrind是运行在Linux上的一套基于仿真技术的程序调试和分析工具,作者是获得过Google-O'Reilly开源大奖的Julian Seward,它包含一个内核 ...

  3. 动态内存检测工具Valgrind

    1. Valgrind查找内存泄露利器 Valgrind是一个GPL的软件,用于Linux(For x86, amd64 and ppc32)程序的内存调试和代码剖析.你可以在它的环境中运行你的程序来 ...

  4. C/C++的内存泄漏检测工具Valgrind memcheck的使用经历

    Linux下的Valgrind真是利器啊(不知道Valgrind的请自觉查看参考文献(1)(2)),帮我找出了不少C++中的内存管理错误,前一阵子还在纠结为什么VS 2013下运行良好的程序到了Lin ...

  5. c linux new使内存耗尽_C/C++的内存泄漏检测工具Valgrind memcheck的使用经历

    Linux下的Valgrind真是利器啊(不知道Valgrind的请自觉查看参考文献(1)(2)),帮我找出了不少C++中的内存管理错误,前一阵子还在纠结为什么VS 2013下运行良好的程序到了Lin ...

  6. linux安装系统内存检测,Ubuntu下安装内存检测工具Valgrind

    Ubuntu下安装Valgrind很简单,直接从ubuntu软件中心下载安装,并且还会提供一个简单的图形界面..当然,你也可以在命令行中使用. Valgrind实际上是一个工具集,包含多个调试工具,如 ...

  7. C/C++内存检测工具valgrind

    valgrind是什么 用来检测C/C++程序中出现的内存问题 所有对内存的读写将会被检测 malloc() free() new() delete() 这些函数的调用都会被捕获 相关检测的内容 1. ...

  8. 内存检测王者之剑—valgrind

    记得在大学的刚开始学习C/C++的时候,对于内存问题一点也没有关心过,其实也是关心比较少,知道后来才慢慢注意起来,当时排查是否有内存泄漏全靠手,去看看malloc和free或者new和delete是否 ...

  9. Ubuntu下内存泄露检测工具Valgrind的使用

    在VS中可以用VLD检测是否有内存泄露,可以参考http://blog.csdn.net/fengbingchun/article/details/44195959,下面介绍下Ubuntu中内存泄露检 ...

  10. Windows和Linux内存检测工具:Valgrind,Visual Leak Detector,CppCheck, Cpplint

    1 Linux内存泄漏检测工具Valgrind Valgrind简介 Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合.Valgrind由内核(core)以及基于内核 ...

最新文章

  1. BusinessObject J2EE单点登陆简单使用
  2. Hadoop架构-YARN
  3. 缩进动画Scaleanimation的一个小示例
  4. To B设计系统 - 在平平淡淡中开花结果
  5. Flask 系列之 Blueprint
  6. 【转】Linux中多线程wait使用注意
  7. UE4学习-在虚幻编辑器中打开VS的三种方式
  8. webpack打包样式资源_使用loader去打包css文件_打包less文件---webpack工作笔记004
  9. Java自带的keytool命令
  10. BlenderPython (三)bpy模块
  11. 太强了,头发丝完整保留!一个开源的 Python 实时视频抠图工具
  12. 逻辑漏洞(基本概念、爆破)
  13. MATLAB生成(对角线上元素相同的)三对角矩阵的实例
  14. 手机端和PC端开发区别
  15. eleme 项目使用到的库
  16. Codeforces ~ 1009C ~ Annoying Present (贪心)
  17. 软件测试周刊(第86期):一个人为寻求他所需要的东西,走遍了全世界。回到家里,找到了。
  18. arXiv每日推荐-5.16:语音/音频每日论文速递
  19. 批量缩小图片大小的方法
  20. winSCP 集成PuTTY附下载

热门文章

  1. 用mysql+php开发网上商城系统
  2. 覆盖常见四大应用场景,华为云CDN能够更好满足企业业务加速需求
  3. 【高级Java开发】类QQ聊天工具的设计与实现(代码已上传)
  4. CVPR 2020 | 旷视研究院探究优化场景文字识别的「词汇依赖」问题
  5. fedora linux搜狗输入法,在Fedora 28系统下安装搜狗输入法
  6. basic4android计算器,vb三角函数计算器代码
  7. 使用 VS 2008 编译 ECW SDK 3.3
  8. requests使用socks代理
  9. 火车头采集器如何自制php插件
  10. 1个球从100m落下,每次时,反跳原高度的一半,再落,再反弹,求第10次落地共经过多少m,第10次反弹多高。 谭浩强《c语言程序设计》第五章第十一题