一、valgrind简介

Valgrind是一款用于内存调试、内存泄漏检测以及性能分析、检测线程错误的软件开发工具。

Valgrind 是运行在Linux 上的多用途代码剖析和内存调试软件。主要包括Memcheck、Callgrind、Cachegrind 等工具,每个工具都能完成一项任务调试、检测或分析。可以检测内存泄露、线程违例和Cache 的使用等。Valgrind 基于仿真方式对程序进行调试,它先于应用程序获取实际处理器的控制权,并在实际处理器的基础上仿真一个虚拟处理器,并使应用程序运行于这个虚拟处理器之上,从而对应用程序的运行进行监视。应用程序并不知道该处理器是虚拟的还是实际的,已经编译成二进制代码的应用程序并不用重新进行编译,Valgrind 直接解释二进制代码使得应用程序基于它运行,从而能够检查内存操作时可能出现的错误。所以在Valgrind下运行的程序运行速度要慢得多,而且使用的内存要多得多 - 例如,Memcheck工具下的程序是正常情况的两倍多。因此,最好在性能好的机器上使用Valgrind。

二、安装valgrind

wget https://sourceware.org/pub/valgrind/valgrind-3.15.0.tar.bz2

wyj@wyj-virtual-machine:~/Download$ tar -xjvf valgrind-3.15.0.tar.bz2

wyj@wyj-virtual-machine:~/Download$ cd valgrind-3.15.0/

因为valgrind支持多个平台,根据当前主机配置valgrind

wyj@wyj-virtual-machine:~/Download/valgrind-3.15.0$ ./configure

./configure之后就有makefile出现,接着就是make编译,安装

wyj@wyj-virtual-machine:~/Download/valgrind-3.15.0$ make

wyj@wyj-virtual-machine:~/Download/valgrind-3.15.0$ sudo make install

查看一下版本看看是否安装好

wyj@wyj-virtual-machine:~/Download/valgrind-3.15.0$ valgrind --version

valgrind-3.15.0

三、valgrind使用

因为我也是第一次用,所以就先试试官方的快速入门试试,慢慢探索它的功能

#include <stdio.h>#include <stdlib.h>void fun(void){int *x = malloc(10*sizeof(int));x [10] = 0; //问题1:堆块溢出} //问题2:内存泄漏 -  x未释放int main(int argc, char **argv){fun() ;return 0 ;}

编译程序-g以包含调试信息,以便Memcheck的错误消息包含确切的行号

wyj@wyj-virtual-machine:~/c_code$ gcc -g valgrind_test.c -o valgrind_test

正常运行

wyj@wyj-virtual-machine:~/c_code$ ./valgrind_test

Memcheck是默认工具。--leak-check 选项打开详细的内存泄漏检测器。程序运行速度会比正常情况慢很多(例如20到30倍),并且会占用更多内存。Memcheck将发出有关内存错误和检测到的泄漏的消息。

wyj@wyj-virtual-machine:~/c_code$ valgrind --leak-check=yes ./valgrind_test

一开始是valgrind信息“==62414==”表示进程号

==62414== Memcheck, a memory error detector

==62414== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.

==62414== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info

==62414== Command: ./valgrind_test

程序访问非法地址的内存,无效写入

==62414== Invalid write of size 4

==62414==    at 0x40054B: fun (valgrind_test.c:21)

==62414==    by 0x400566: main (valgrind_test.c:28)

==62414==  Address 0x5201068 is 0 bytes after a block of size 40 alloc'd

==62414==    at 0x4C2AEC3: malloc (vg_replace_malloc.c:309)

==62414==    by 0x40053E: fun (valgrind_test.c:20)

==62414==    by 0x400566: main (valgrind_test.c:28)

==62414==

堆区情况:

==62414== HEAP SUMMARY:

==62414==     in use at exit: 40 bytes in 1 blocks

==62414==   total heap usage: 1 allocs, 0 frees, 40 bytes allocated

内存泄漏消息如下所示:

==62414== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1

==62414==    at 0x4C2AEC3: malloc (vg_replace_malloc.c:309)

==62414==    by 0x40053E: fun (valgrind_test.c:20)

==62414==    by 0x400566: main (valgrind_test.c:28)

有几种泄漏; 两个最重要的类别是,肯定泄露(definitely lost),可能已经泄露(possibly lost)

==62414== LEAK SUMMARY:

==62414==    definitely lost: 40 bytes in 1 blocks

==62414==    indirectly lost: 0 bytes in 0 blocks

==62414==      possibly lost: 0 bytes in 0 blocks

==62414==    still reachable: 0 bytes in 0 blocks

==62414==         suppressed: 0 bytes in 0 blocks

==62414==

==62414== For lists of detected and suppressed errors, rerun with: -s

==62414== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

关于Memcheck的错误消息说明:

http://valgrind.org/docs/manual/mc-manual.html#mc-manual.errormsgs

Valgrind直接与现有可执行文件一起使用。无需重新编译,重新链接或以其他方式修改要检查的程序。

使用方法:

wyj@wyj-virtual-machine:~/c_code$ valgrind --help

usage: valgrind [options] prog-and-args

valgrind [valgrind-options] your-prog [your-prog-options]

最重要的选项是--tool决定运行哪个Valgrind工具。例如,如果要ls -l使用内存检查工具Memcheck 运行该命令 ,请发出以下命令

wyj@wyj-virtual-machine:~$ valgrind --tool=memcheck ls -l

==62521== Memcheck, a memory error detector

==62521== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.

==62521== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info

==62521== Command: ls -l

==62521==

总用量 148

drwxrwxr-x  9 wyj  wyj   4096 12月 26  2018 apue

drwxrwxr-x  5 wyj  wyj   4096  8月 11 10:40 c_code

drwxrwxr-x  2 wyj  wyj   4096  7月 31 16:56 crc

drwxrwxr-x 13 wyj  wyj   4096  8月 11 10:12 Download

......

==62521==

==62521== HEAP SUMMARY:

==62521==     in use at exit: 20,073 bytes in 29 blocks

==62521==   total heap usage: 266 allocs, 237 frees, 94,000 bytes allocated

==62521==

==62521== LEAK SUMMARY:

==62521==    definitely lost: 0 bytes in 0 blocks

==62521==    indirectly lost: 0 bytes in 0 blocks

==62521==      possibly lost: 0 bytes in 0 blocks

==62521==    still reachable: 20,073 bytes in 29 blocks

==62521==         suppressed: 0 bytes in 0 blocks

==62521== Rerun with --leak-check=full to see details of leaked memory

==62521==

==62521== For lists of detected and suppressed errors, rerun with: -s

==62521== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Memcheck是默认设置,可以不用加tool直接使用

wyj@wyj-virtual-machine:~$ valgrind  ls -l

Valgrind一般包含下列工具:

1.Memcheck

最常用的工具,用来检测程序中出现的内存问题,所有对内存的读写都会被检测到,一切对malloc()/free()/new/delete的调用都会被捕获。所以,它能检测以下问题:

1.对未初始化内存的使用;

2.读/写释放后的内存块;

3.读/写超出malloc分配的内存块;

4.读/写不适当的栈中内存块;

5.内存泄漏,指向一块内存的指针永远丢失;

6.不正确的malloc/free或new/delete匹配;

7,memcpy()相关函数中的dst和src指针重叠。

这些问题往往是C/C++程序员最头疼的问题,Memcheck在这里帮上了大忙。

2.Callgrind

和gprof类似的分析工具,但它对程序的运行观察更是入微,能给我们提供更多的信息。和gprof不同,它不需要在编译源代码时附加特殊选项,但加上调试选项是推荐的。Callgrind收集程序运行时的一些数据,建立函数调用关系图,还可以有选择地进行cache模拟。在运行结束时,它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式。

3.Cachegrind

Cache分析器,它模拟CPU中的一级缓存I1,Dl和二级缓存,能够精确地指出程序中cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数。这对优化程序有很大的帮助。

4.Helgrind

它主要用来检查多线程程序中出现的竞争问题。Helgrind寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误。Helgrind实现了名为“Eraser”的竞争检测算法,并做了进一步改进,减少了报告错误的次数。不过,Helgrind仍然处于实验阶段。

5. Massif

堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率。

此外,lackey和nulgrind也会提供。Lackey是小型工具,很少用到;Nulgrind只是为开发者展示如何创建一个工具。我们就不做介绍了。

多线程检查工具的使用:

valgrind --tool=helgrind prog-and-args使用多线程调试工具

#include <stdio.h>#include <pthread.h>#include <string.h>#include <errno.h>#include <unistd.h>void * thread_worker1(void *args) ;typedef struct worker_ctx_s{int             shared_var  ;pthread_mutex_t lock ;} worker_ctx_t ;void *thread_worker1(void *args){worker_ctx_t    *ctx = (worker_ctx_t *)args ;if(!args){printf("%s() get invalid arguments\n", __FUNCTION__) ; // __FUNCTION__ get function namepthread_exit(NULL) ;}printf("Thread worker1 [%ld] start running...\n", pthread_self()) ;/* 两次上锁导致死锁  */pthread_mutex_lock(&(ctx->lock)) ;pthread_mutex_lock(&(ctx->lock)) ;pthread_mutex_unlock( &ctx->lock ) ;sleep(1) ;printf("Thread worker1 exit...\n") ;pthread_exit(NULL) ;return NULL ;}int main(int argc, char **argv){worker_ctx_t    worker_ctx ;pthread_t       tid ;pthread_attr_t  thread_attr ;worker_ctx.shared_var = 1000 ;pthread_mutex_init(&worker_ctx.lock, NULL) ;if ( pthread_attr_init(&thread_attr) != 0 ){printf("pthread_attr_init() failed: %s\n", strerror(errno)) ;return -1 ;}if ( pthread_attr_setstacksize( &thread_attr, 1024*120) != 0 ){printf("pthread_setstacksize() failure: %s\n", strerror(errno) ) ;return -2 ;}if ( pthread_attr_setdetachstate(&thread_attr,  PTHREAD_CREATE_DETACHED) != 0 ){printf("pthread_attr_setdetachstate() error: %s\n", strerror(errno)) ;return -3 ;}/*    Create thread    */pthread_create(&tid, &thread_attr,  thread_worker1, &worker_ctx);if ( pthread_attr_destroy(&thread_attr) != 0 ){printf("pthread_attr_destroy() failed :%s\n", strerror(errno)) ;return -4 ;}sleep(5) ;return 0 ;
}

wyj@wyj-virtual-machine:~/c_code$ gcc -g valgrind_test_helgrand.c -o valgrind_test_helgrand -lpthread

wyj@wyj-virtual-machine:~/c_code$ valgrind --tool=helgrind ./valgrind_test_helgrand

==63432== Helgrind, a thread error detector

==63432== Copyright (C) 2007-2017, and GNU GPL'd, by OpenWorks LLP et al.

==63432== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info

==63432== Command: ./valgrind_test_helgrand

程序打印的消息

Thread worker1 [67376896] start running...

==63432== ---Thread-Announcement------------------------------------------

两个线程被创建

==63432== Thread #2 was created

==63432==    at 0x5158FFE: clone (clone.S:74)

==63432==    by 0x4E44199: do_clone.constprop.3 (createthread.c:75)

==63432==    by 0x4E458BA: create_thread (createthread.c:245)

==63432==    by 0x4E458BA: pthread_create@@GLIBC_2.2.5 (pthread_create.c:611)

==63432==    by 0x4C31CBA: pthread_create_WRK (hg_intercepts.c:427)

==63432==    by 0x4C32D98: pthread_create@* (hg_intercepts.c:460)

==63432==    by 0x400CA2: main (valgrind_test_helgrand.c:84)

==63432==

==63432== ----------------------------------------------------------------

尝试重新锁定本身已持有的非递归锁

==63432== Thread #2: Attempt to re-lock a non-recursive lock I already hold

==63432==    at 0x4C2F259: mutex_lock_WRK (hg_intercepts.c:899)

==63432==    by 0x4C3317D: pthread_mutex_lock (hg_intercepts.c:925)

==63432==    by 0x400B5C: thread_worker1 (valgrind_test_helgrand.c:44)

==63432==    by 0x4C31EAE: mythread_wrapper (hg_intercepts.c:389)

==63432==    by 0x4E45183: start_thread (pthread_create.c:312)

==63432==    by 0x515903C: clone (clone.S:111)

锁之前已经获取过

==63432==  Lock was previously acquired

==63432==    at 0x4C2F320: mutex_lock_WRK (hg_intercepts.c:909)

==63432==    by 0x4C3317D: pthread_mutex_lock (hg_intercepts.c:925)

==63432==    by 0x400B4C: thread_worker1 (valgrind_test_helgrand.c:43)

==63432==    by 0x4C31EAE: mythread_wrapper (hg_intercepts.c:389)

==63432==    by 0x4E45183: start_thread (pthread_create.c:312)

==63432==    by 0x515903C: clone (clone.S:111)

==63432==

==63432== ----------------------------------------------------------------

退出线程时任保持一个锁

==63432== Thread #2: Exiting thread still holds 1 lock

==63432==    at 0x4E4BF1C: __lll_lock_wait (lowlevellock.S:135)

==63432==    by 0x4E47648: _L_lock_909 (pthread_mutex_lock.c:151)

==63432==    by 0x4E4746E: pthread_mutex_lock (pthread_mutex_lock.c:79)

==63432==    by 0x4C2F2BB: mutex_lock_WRK (hg_intercepts.c:902)

==63432==    by 0x4C3317D: pthread_mutex_lock (hg_intercepts.c:925)

==63432==    by 0x400B5C: thread_worker1 (valgrind_test_helgrand.c:44)

==63432==    by 0x4C31EAE: mythread_wrapper (hg_intercepts.c:389)

==63432==    by 0x4E45183: start_thread (pthread_create.c:312)

==63432==    by 0x515903C: clone (clone.S:111)

==63432==

==63432==

==63432== Use --history-level=approx or =none to gain increased speed, at

==63432== the cost of reduced accuracy of conflicting-access information

==63432== For lists of detected and suppressed errors, rerun with: -s

==63432== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 26 from 25)

好好分析valgrind调试信息就能知道有没有错误,错误在哪,错误原因是什么,也是刚了解valgrind这个工具,之后再慢慢探索它的功能。

valgrind简介与使用相关推荐

  1. valgrind 简介(内存检查工具)

    1. valgrind 简介 1. valgrind 简介 1.1. 概图 1.2. 特点 1.3. 使用示例 1.4. 参数说明 1.4.1. 常用参数 1.4.2. 展示 1.4.3. 子进程.动 ...

  2. 内存泄漏查找工具----valgrind简介与使用

    目录 1 valgrind简介 2 常用参数 3 使用示例 用了一下asan,感觉比valgrid好用,以后用asan,asan的使用方法内存错误分析工具----asan(AddressSanitiz ...

  3. 【Bash百宝箱】valgrind简介

    Valgrind官网请参考如下网址: http://valgrind.org/ 1. Valgrind简介 Valgrind定义为framework,用来构建动态分析工具,这些Valgrind工具可以 ...

  4. #内存泄露# #valgrind# valgrind简介

    #内存泄露# #valgrind# valgrind使用 https://blog.csdn.net/xiaoting451292510/article/details/104943986 #内存泄露 ...

  5. 使用valgrind分析C程序调用线路图

    Valgrind可以检测内存泄漏和内存违例,但是用Valgrind生成的日志信息结合kcachegrind就可以查看C程序的执行线路图,调用时间,是做性能优化和查看代码的非常好的工具. 1.下载安装 ...

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

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

  7. valgrind小结

    一.valgrind简介 Valgrind是一款用于内存调试.内存泄漏检测以及性能分析.检测线程错误的软件开发工具. Valgrind一般包含下列工具: 1.Memcheck 最常用的工具,用来检测程 ...

  8. 理想与现实:HI3516编译Valgrind

    众所周知,C/C++程序的内存问题较多.Valgrind 是一个用于构建动态分析工具的工具框架.其包含的工具可以自动检测许多内存管理和线程错误,并详细剖析程序. 于是,我希望在海思系列芯片上使用它.编 ...

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

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

最新文章

  1. JAVA并发-从缓存一致性说volatile 讲的很好
  2. Git初学札记(二)————EGit导入远程Git仓库项目(Clone操作)
  3. NUC1313 皇帝的金币
  4. linux 安装scons
  5. 《Java程序设计教程 实验手册》pdf 附下载链接
  6. 微软服务器探针产品,服务器云探针
  7. 计算机电源管理器怎么打开,联想电池管理如何使用_联想电源管理软件在哪里打开-win7之家...
  8. 清华技术经理自学Python全栈的从业笔记,欢迎收藏
  9. NATAPP内网穿透使用
  10. Ubuntu16.04快速安装搜狗拼音输入法
  11. Linux_Centos7在安装Mysql常见错误依赖时失败——error: Failed dependencies:mariadb-libs is obsoleted
  12. 解决ubuntu16.04无法打开网易云音乐
  13. 同频切换的事件_目前现网中,LTE同频切换主要是通过A5事件进行触发
  14. 【基于Java语言的Android个人开发笔记,开屏引导页】利用ViewPagerFragment实现引导页
  15. pada mysql
  16. 《慢慢来,一切都来得及》语录
  17. iOS 15.0+ 中 SwiftUI 顶部或底部悬浮功能小面板的极简实现
  18. CPU降温软件测试自学,CPU降温软件真的有用吗工作原理是什么
  19. android 流播放器开发,GitHub - youcoding98/FastVideo: 基于Android平台的移动流媒体播放器的开发...
  20. 作为优秀的DBA,究竟需要掌握多少种数据库?

热门文章

  1. 徐氏银行开业了!!!!秒杀一切!!!!!
  2. 计算机2级可以搞小抄吗,份计算机二级C语言上机题库可缩印做小抄百分百准确.doc...
  3. 运维基础知识硬件总结
  4. 申请实用新型专利有什么优势
  5. 自由人NFT:无聊猿NFT的前世今生
  6. Linux删除安卓温控,玩机高手不容错过!体积仅1M的神级安卓工具箱
  7. 删除Flash控件的 Flash9e.ocx和FlashUtil9e.exe
  8. .trc与.trm文件
  9. 益百分与爱同行演绎健康品牌新温度
  10. TOM随心邮——一款好用的移动办公利器