zoukankan      html  css  js  c++  java
  • ubuntu 上使用valgrind

      Valgrind是一个GPL的软件,用于Linux(For x86, amd64 and ppc32)程序的内存调试和代码剖析。你可以在它的环境中运行你的程序来监视内存的使用情况,比如C 语言中的malloc和free或者 C++中的new和 delete。使用Valgrind的工具包,你可以自动的检测许多内存管理和线程的bug,避免花费太多的时间在bug寻找上,使得你的程序更加稳固。

      Valgrind的主要功能
      Valgrind工具包包含多个工具,如Memcheck,Cachegrind,Helgrind, Callgrind,Massif。下面分别介绍个工具的作用:

    Memcheck 工具主要检查下面的程序错误:

      1.使用未初始化的内存 (Use of uninitialised memory)
      2.使用已经释放了的内存 (Reading/writing memory after it has been free’d)
      3.使用超过 malloc分配的内存空间(Reading/writing off the end of malloc’d blocks)
      4.对堆栈的非法访问 (Reading/writing inappropriate areas on the stack)
      5.申请的空间是否有释放 (Memory leaks – where pointers to malloc’d blocks are lost forever)
      6.malloc/free/new/delete申请和释放内存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])
      7.src和dst的重叠(Overlapping src and dst pointers in memcpy() and related functions)
    Callgrind
      Callgrind收集程序运行时的一些数据,函数调用关系等信息,还可以有选择地进行cache 模拟。在运行结束时,它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式。

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

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

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

    Ubuntu 安装valgrind:

    #> sudo apt-get install valgrind

    valgrind 使用:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main()
    {
    
        char *ptr = (char *)malloc(1024);
        
        ptr[1024] = 0; //
    
        memcpy(ptr+1, ptr, 100);
    
        char ch = ptr[1024];
    
        free(ptr);
        free(ptr);
    
        char *ptr1;
        *ptr1 = 'a';
    
        char *ptr2 = (char *)malloc(1024);
    
        return 0;
    }

    #> valgrind --tool=memcheck --leak-check=yes ./valgTest

      注意在编译程序的时候加上-g选项,打印错误信息的时候会给出行号。上面的执行结果给出了六个错误。

      下面看一个多线程竞争的情况:

    #include <pthread.h>
    #include <stdio.h>
     
    int a = 0;
     
    void* child_fn (void* arg)
    {
             a++;
             return NULL;
    }
     
    int main () 
    {
             pthread_t child;
             pthread_create(&child,NULL, child_fn, NULL);
             a++;
             pthread_join(child,NULL);
             return 0;
    }

    zhuyp@ubuntu:~/valgrind$ valgrind --tool=helgrind ./helTest
    ==5639== Helgrind, a thread error detector
    ==5639== Copyright (C) 2007-2013, and GNU GPL'd, by OpenWorks LLP et al.
    ==5639== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
    ==5639== Command: ./helTest
    ==5639==
    ==5639== ---Thread-Announcement------------------------------------------
    ==5639==
    ==5639== Thread #1 is the program's root thread
    ==5639==
    ==5639== ---Thread-Announcement------------------------------------------
    ==5639==
    ==5639== Thread #2 was created
    ==5639== at 0x51562CE: clone (clone.S:74)
    ==5639== by 0x4E44199: do_clone.constprop.3 (createthread.c:75)
    ==5639== by 0x4E458BA: pthread_create@@GLIBC_2.2.5 (createthread.c:245)
    ==5639== by 0x4C30C90: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
    ==5639== by 0x40068D: main (helTest.c:15)
    ==5639==
    ==5639== ----------------------------------------------------------------
    ==5639==
    ==5639== Possible data race during read of size 4 at 0x60104C by thread #1
    ==5639== Locks held: none
    ==5639== at 0x40068E: main (helTest.c:16)
    ==5639==
    ==5639== This conflicts with a previous write of size 4 by thread #2
    ==5639== Locks held: none
    ==5639== at 0x40065E: child_fn (helTest.c:8)
    ==5639== by 0x4C30E26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
    ==5639== by 0x4E45181: start_thread (pthread_create.c:312)
    ==5639== by 0x515630C: clone (clone.S:111)
    ==5639==
    ==5639== ----------------------------------------------------------------
    ==5639==
    ==5639== Possible data race during write of size 4 at 0x60104C by thread #1
    ==5639== Locks held: none
    ==5639== at 0x400697: main (helTest.c:16)
    ==5639==
    ==5639== This conflicts with a previous write of size 4 by thread #2
    ==5639== Locks held: none
    ==5639== at 0x40065E: child_fn (helTest.c:8)
    ==5639== by 0x4C30E26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
    ==5639== by 0x4E45181: start_thread (pthread_create.c:312)
    ==5639== by 0x515630C: clone (clone.S:111)
    ==5639==
    ==5639==
    ==5639== For counts of detected and suppressed errors, rerun with: -v
    ==5639== Use --history-level=approx or =none to gain increased speed, at
    ==5639== the cost of reduced accuracy of conflicting-access information
    ==5639== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

     前面写过一个使用coredump调试死锁的方法,这里使用valgrind 的 helgrind 工具也可以检查出死锁问题。

    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <chrono>
    using namespace std;
    
    mutex m1,m2;
    
    
    void func_2()
    {
        m2.lock();
        cout<< "about to dead_lock"<<endl;
        m1.lock();
        
    }
    
    void func_1()
    {
        m1.lock();
        
        chrono::milliseconds dura( 1000 );// delay to trigger dead_lock
        this_thread::sleep_for( dura );
            
        m2.lock();
        
    }
    
    
    int main()
    {
    
        thread t1(func_1);
    
        thread t2(func_2);
        
        t1.join();
        t2.join();
        return 0;
    
    }

    zhuyp@ubuntu:~/valgrind$ g++ -Wall dead_lock_demo.cpp -o dead_lock_demo -g -std=c++11 -lpthread
    zhuyp@ubuntu:~/valgrind$ valgrind --tool=helgrind ./dead_lock_demo
    ==5646== Helgrind, a thread error detector
    ==5646== Copyright (C) 2007-2013, and GNU GPL'd, by OpenWorks LLP et al.
    ==5646== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
    ==5646== Command: ./dead_lock_demo
    ==5646==
    about to dead_lock  // 执行到这里,Ctrl + C 结束进程,则打印出如下信息
    ^C==5646== ---Thread-Announcement------------------------------------------ 
    ==5646==
    ==5646== Thread #2 was created
    ==5646== at 0x56702CE: clone (clone.S:74)
    ==5646== by 0x4E44199: do_clone.constprop.3 (createthread.c:75)
    ==5646== by 0x4E458BA: pthread_create@@GLIBC_2.2.5 (createthread.c:245)
    ==5646== by 0x4C30C90: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
    ==5646== by 0x510CE3E: std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
    ==5646== by 0x401789: std::thread::thread<void (&)()>(void (&)()) (thread:135)
    ==5646== by 0x40112D: main (dead_lock_demo.cpp:33)
    ==5646==
    ==5646== ----------------------------------------------------------------
    ==5646==
    ==5646== Thread #2: Exiting thread still holds 1 lock
    ==5646== at 0x4E4BF2C: __lll_lock_wait (lowlevellock.S:135)
    ==5646== by 0x4E47656: _L_lock_909 (pthread_mutex_lock.c:151)
    ==5646== by 0x4E4747E: pthread_mutex_lock (pthread_mutex_lock.c:79)
    ==5646== by 0x4C32072: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
    ==5646== by 0x40101B: __gthread_mutex_lock(pthread_mutex_t*) (gthr-default.h:748)
    ==5646== by 0x401421: std::mutex::lock() (mutex:134)
    ==5646== by 0x401111: func_1() (dead_lock_demo.cpp:25)
    ==5646== by 0x40278C: void std::_Bind_simple<void (*())()>::_M_invoke<>(std::_Index_tuple<>) (functional:1732)
    ==5646== by 0x4026E6: std::_Bind_simple<void (*())()>::operator()() (functional:1720)
    ==5646== by 0x40267F: std::thread::_Impl<std::_Bind_simple<void (*())()> >::_M_run() (thread:115)
    ==5646== by 0x510CBEF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
    ==5646== by 0x4C30E26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
    ==5646==
    ==5646== ---Thread-Announcement------------------------------------------
    ==5646==
    ==5646== Thread #3 was created
    ==5646== at 0x56702CE: clone (clone.S:74)
    ==5646== by 0x4E44199: do_clone.constprop.3 (createthread.c:75)
    ==5646== by 0x4E458BA: pthread_create@@GLIBC_2.2.5 (createthread.c:245)
    ==5646== by 0x4C30C90: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
    ==5646== by 0x510CE3E: std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
    ==5646== by 0x401789: std::thread::thread<void (&)()>(void (&)()) (thread:135)
    ==5646== by 0x40113E: main (dead_lock_demo.cpp:35)
    ==5646==
    ==5646== ----------------------------------------------------------------
    ==5646==
    ==5646== Thread #3: Exiting thread still holds 1 lock
    ==5646== at 0x4E4BF2C: __lll_lock_wait (lowlevellock.S:135)
    ==5646== by 0x4E47656: _L_lock_909 (pthread_mutex_lock.c:151)
    ==5646== by 0x4E4747E: pthread_mutex_lock (pthread_mutex_lock.c:79)
    ==5646== by 0x4C32072: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
    ==5646== by 0x40101B: __gthread_mutex_lock(pthread_mutex_t*) (gthr-default.h:748)
    ==5646== by 0x401421: std::mutex::lock() (mutex:134)
    ==5646== by 0x4010DF: func_2() (dead_lock_demo.cpp:14)
    ==5646== by 0x40278C: void std::_Bind_simple<void (*())()>::_M_invoke<>(std::_Index_tuple<>) (functional:1732)
    ==5646== by 0x4026E6: std::_Bind_simple<void (*())()>::operator()() (functional:1720)
    ==5646== by 0x40267F: std::thread::_Impl<std::_Bind_simple<void (*())()> >::_M_run() (thread:115)
    ==5646== by 0x510CBEF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
    ==5646== by 0x4C30E26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
    ==5646==
    ==5646==
    ==5646== For counts of detected and suppressed errors, rerun with: -v
    ==5646== Use --history-level=approx or =none to gain increased speed, at
    ==5646== the cost of reduced accuracy of conflicting-access information
    ==5646== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 1 from 1)

    吐槽一下,刚刚在Linux操作并编辑该博文,各种不适应啊,还是换到Windows下来编辑要方便些。。。

  • 相关阅读:
    lock free
    Solr 开发环境搭建
    Web中实现网页跳转的方法大总结:
    CSS定位中最难理解的她——absolute的探讨
    JavaScript中正则表达式中遇到的问题——测试匹配
    编写一个Android平台遇到的所有问题(一)——查询sqlite数据库时遇到的问题
    初来乍到,大家好
    在stackoverflow上使用markdown
    提升debian中字体效果
    vim pathogen自动配置
  • 原文地址:https://www.cnblogs.com/zhuyp1015/p/3901191.html
Copyright © 2011-2022 走看看