×

签到

分享到微信

打开微信,使用扫一扫进入页面后,点击右上角菜单,

点击“发送给朋友”或“分享到朋友圈”完成分享

Valgrind基础调试方法 踏雪寻梅2021-08-17 14:32:21 回复 2 查看 经验交流
Valgrind基础调试方法
分享到:

valgrind基本使用

valgrind介绍

valgrind安装

wget ftp://sourceware.org/pub/valgrind/valgrind-3.17.0.tar.bz2
tar -jxvf valgrind-3.17.0.tar.bz2
cd valgrind-3.17.0
./configure && make
sudo make install

常用工具

  1. memcheck:检查程序中的内存问题,如泄漏、越界、非法指针等。

  2. callgrind:检测程序代码覆盖,以及分析程序性能。

  3. cachegrind:分析CPU的cache命中率、丢失率,用于进行代码优化。

  4. helgrind:用于检查多线程程序的竞态条件。

  5. massif:堆栈分析器,指示程序中使用了多少堆内存等信息。

memcheck

内存泄漏

  1. 程序代码如下,gcc编译时需加-g参数:

  2. void mal0(){
    void* array = malloc(sizeof(int));
    }
    int main(){
    mal0();
    return 0;
    }
  3. 执行valgraind使用memcheck工具:

  4. valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all ./test_c
  5.  得到输出log如下:

  6. ==23282== Memcheck, a memory error detector
    ==23282== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==23282== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
    ==23282== Command: ./test_c
    ==23282==
    ==23282==
    ==23282== HEAP SUMMARY:
    ==23282== in use at exit: 4 bytes in 1 blocks
    ==23282== total heap usage: 1 allocs, 0 frees, 4 bytes allocated
    ==23282==
    ==23282== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
    ==23282== at 0x4C2F03A: malloc (vg_replace_malloc.c:380)
    ==23282== by 0x4005F4: mal1 (mal.c:10)
    ==23282== by 0x400642: main (mal.c:20)
    ==23282==
    ==23282== LEAK SUMMARY:
    ==23282== definitely lost: 4 bytes in 1 blocks
    ==23282== indirectly lost: 0 bytes in 0 blocks
    ==23282== possibly lost: 0 bytes in 0 blocks
    ==23282== still reachable: 0 bytes in 0 blocks
    ==23282== suppressed: 0 bytes in 0 blocks
    ==23282==
    ==23282== For lists of detected and suppressed errors, rerun with: -s
    ==23282== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
  7. 命令分析

  8. --tool=memcheck:此时使用的valgrind工具,默认memcheck
    --leak-check:指定如何报告内存泄漏
    no 不报告
    summary 显示简要信息,有多少个内存泄漏。summary是缺省值。
    yes 和 full 显示每个泄漏的内存在哪里分配。
    show-leak-kinds: 指定显示内存泄漏的类型的组合。类型包括definite, indirect, possible,reachable。也可以指定all或none。缺省值是definite,possible。
  9. log分析

    image.png

  10. 左侧为进程ID
    右1为valgrind版本信息等
    右2为HEAP SUMMARY,他表示程序在堆上分配内存的情况。当前分析的结果,如图所示:1 allocs, 0 frees, 4 bytes allocated代表申请1次,释放0次,分配了4字节内存。之后会显示详细的代码调用,可知时mal1函数导致了内存泄漏。
    右3为当前总结,definitely lost: 4 bytes in 1 blocks代表实锤丢了4个字节
    。
    Definitely lost:找不到指向该块的指针
    Indirectly lost:块间接丢失
    possibly lost:存在指向该块的"内部指针"。memcheck无法确定是否为合法
    Still reachable:可以找到指向该内存块的"开始指针"。理论上程序退出前,可以通过这些指针来释放内存。
  11. 如果使用g++编译,会出现如下情况,出现两次申请未释放

  12. ==23363== Memcheck, a memory error detector
    ==23363== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==23363== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
    ==23363== Command: ./test_c
    ==23363==
    ==23363==
    ==23363== HEAP SUMMARY:
    ==23363== in use at exit: 72,708 bytes in 2 blocks
    ==23363== total heap usage: 2 allocs, 0 frees, 72,708 bytes allocated
    ==23363==
    ==23363== 4 bytes in 1 blocks are definitely lost in loss record 1 of 2
    ==23363== at 0x4C2F03A: malloc (vg_replace_malloc.c:380)
    ==23363== by 0x4007D4: mal1() (mal.c:11)
    ==23363== by 0x40081D: main (mal.c:21)
    ==23363==
    ==23363== 72,704 bytes in 1 blocks are still reachable in loss record 2 of 2
    ==23363== at 0x4C2F03A: malloc (vg_replace_malloc.c:380)
    ==23363== by 0x4EC8EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
    ==23363== by 0x40106F9: call_init.part.0 (dl-init.c:72)
    ==23363== by 0x401080A: call_init (dl-init.c:30)
    ==23363== by 0x401080A: _dl_init (dl-init.c:120)
    ==23363== by 0x4000C69: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so)
    ==23363==
    ==23363== LEAK SUMMARY:
    ==23363== definitely lost: 4 bytes in 1 blocks
    ==23363== indirectly lost: 0 bytes in 0 blocks
    ==23363== possibly lost: 0 bytes in 0 blocks
    ==23363== still reachable: 72,704 bytes in 1 blocks
    ==23363== suppressed: 0 bytes in 0 blocks
    ==23363==
    ==23363== For lists of detected and suppressed errors, rerun with: -s
    ==23363== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
  13. log分析

    image.png

  • 这是因为C++为了提高效率,使用的内存池机制。当程序终止时,其内存才会被操作系统回收,因此valgrind将72,704大小报为reachable。

内存越界

  1. 编写如下代码,带-g编译

  2. valgrind查看:valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all ./read

  3. log信息

  4. ==23850== Memcheck, a memory error detector
    ==23850== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==23850== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
    ==23850== Command: ./read
    ==23850==
    ==23850== Invalid read of size 4
    ==23850== at 0x4009B4: read() (read.cpp:7)
    ==23850== by 0x400A2D: main (read.cpp:11)
    ==23850== Address 0x5abbc90 is 0 bytes after a block of size 16 alloc'd
    ==23850== at 0x4C2F75B: operator new(unsigned long) (vg_replace_malloc.c:417)
    ==23850== by 0x400F95: __gnu_cxx::new_allocator<int>::allocate(unsigned long, void const*) (new_allocator.h:104)
    ==23850== by 0x400EDF: __gnu_cxx::__alloc_traits<std::allocator<int> >::allocate(std::allocator<int>&, unsigned long) (alloc_traits.h:182)
    ==23850== by 0x400DEB: std::_Vector_base<int, std::allocator<int> >::_M_allocate(unsigned long) (stl_vector.h:170)
    ==23850== by 0x400CC6: void std::vector<int, std::allocator<int> >::_M_initialize_dispatch<int>(int, int, std::__true_type) (stl_vector.h:1249)
    ==23850== by 0x400B11: std::vector<int, std::allocator<int> >::vector<int>(int, int, std::allocator<int> const&) (stl_vector.h:413)
    ==23850== by 0x400996: read() (read.cpp:6)
    ==23850== by 0x400A2D: main (read.cpp:11)
    ==23850==
    vas[4]:0
    ==23850==
    ==23850== HEAP SUMMARY:
    ==23850== in use at exit: 72,704 bytes in 1 blocks
    ==23850== total heap usage: 3 allocs, 2 frees, 73,744 bytes allocated
    ==23850==
    ==23850== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1
    ==23850== at 0x4C2F03A: malloc (vg_replace_malloc.c:380)
    ==23850== by 0x4EC8EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
    ==23850== by 0x40106F9: call_init.part.0 (dl-init.c:72)
    ==23850== by 0x401080A: call_init (dl-init.c:30)
    ==23850== by 0x401080A: _dl_init (dl-init.c:120)
    ==23850== by 0x4000C69: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so)
    ==23850==
    ==23850== LEAK SUMMARY:
    ==23850== definitely lost: 0 bytes in 0 blocks
    ==23850== indirectly lost: 0 bytes in 0 blocks
    ==23850== possibly lost: 0 bytes in 0 blocks
    ==23850== still reachable: 72,704 bytes in 1 blocks
    ==23850== suppressed: 0 bytes in 0 blocks
    ==23850==
    ==23850== For lists of detected and suppressed errors, rerun with: -s
    ==23850== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
  5. 上述log可见,内存越界发生在函数read中,共越界了4个字节,共申请16个字节大小空间

未初始化内存访问

  1. 编写如下代码,加-g编译

  2. valgaind查看:valgrind --tool=memcheck --track-origins=yes ./zero

  3. #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    int main(){
    int x;
    if (51 == x)
    printf("51 kuaile\n");
    }
  4. log分析:

  5. ==29342== Memcheck, a memory error detector
    ==29342== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==29342== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
    ==29342== Command: ./zero
    ==29342==
    ==29342== Conditional jump or move depends on uninitialised value(s)
    ==29342== at 0x400712: main (zero.cpp:7)
    ==29342== Uninitialised value was created by a stack allocation
    ==29342== at 0x400706: main (zero.cpp:5)
    ==29342==
    ==29342==
    ==29342== HEAP SUMMARY:
    ==29342== in use at exit: 72,704 bytes in 1 blocks
    ==29342== total heap usage: 1 allocs, 0 frees, 72,704 bytes allocated
    ==29342==
    ==29342== LEAK SUMMARY:
    ==29342== definitely lost: 0 bytes in 0 blocks
    ==29342== indirectly lost: 0 bytes in 0 blocks
    ==29342== possibly lost: 0 bytes in 0 blocks
    ==29342== still reachable: 72,704 bytes in 1 blocks
    ==29342== suppressed: 0 bytes in 0 blocks
    ==29342== Rerun with --leak-check=full to see details of leaked memory
    ==29342==
    ==29342== For lists of detected and suppressed errors, rerun with: -s
    ==29342== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)


版权所有 © 2024 寒武纪 Cambricon.com 备案/许可证号:京ICP备17003415号-1
关闭