• C++软件开发常用辅助软件——Valgrind


    Valgrind

    Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。该工具内部又包含多个子工具集(如memcheck, cachegrind, callgrind, helgrind等等),每个子工具集相互独立,每一次分析只能选择一个子工具,默认子工具为memcheck。

    用法

    valgrind [valgrind-options] [your-program] [your-program-options]

    示例

    演示代码:

    1 #include <stdio.h>
    2 
    3 int main()
    4 {
    5     int *a = new int[3];
    6     printf("%d
    ", a[0]);
    7     printf("%d
    ", a[4]);
    8     return 0;
    9 }

    显然上述代码存在3处问题。

    1. 第5行申请的内存未释放

    2. 第6行访问了未初始化的变量

    3. 第7行访问了非法地址

    运行检测工具

    valgrind ./a.out

    输出如下

     1 ==6945== Memcheck, a memory error detector
     2 ==6945== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
     3 ==6945== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
     4 ==6945== Command: ./a.out
     5 ==6945== 
     6 ==6945== Conditional jump or move depends on uninitialised value(s)
     7 ==6945==    at 0x57BF132: vfprintf (in /lib64/libc-2.26.so)
     8 ==6945==    by 0x57C69B5: printf (in /lib64/libc-2.26.so)
     9 ==6945==    by 0x4005D3: main (in /home/nosoul/DEV/test/a.out)
    10 ==6945== 
    11 ==6945== Use of uninitialised value of size 8
    12 ==6945==    at 0x57BAF3B: _itoa_word (in /lib64/libc-2.26.so)
    13 ==6945==    by 0x57BE820: vfprintf (in /lib64/libc-2.26.so)
    14 ==6945==    by 0x57C69B5: printf (in /lib64/libc-2.26.so)
    15 ==6945==    by 0x4005D3: main (in /home/nosoul/DEV/test/a.out)
    16 ==6945== 
    17 ==6945== Conditional jump or move depends on uninitialised value(s)
    18 ==6945==    at 0x57BAF45: _itoa_word (in /lib64/libc-2.26.so)
    19 ==6945==    by 0x57BE820: vfprintf (in /lib64/libc-2.26.so)
    20 ==6945==    by 0x57C69B5: printf (in /lib64/libc-2.26.so)
    21 ==6945==    by 0x4005D3: main (in /home/nosoul/DEV/test/a.out)
    22 ==6945== 
    23 ==6945== Conditional jump or move depends on uninitialised value(s)
    24 ==6945==    at 0x57BE8D8: vfprintf (in /lib64/libc-2.26.so)
    25 ==6945==    by 0x57C69B5: printf (in /lib64/libc-2.26.so)
    26 ==6945==    by 0x4005D3: main (in /home/nosoul/DEV/test/a.out)
    27 ==6945== 
    28 ==6945== Conditional jump or move depends on uninitialised value(s)
    29 ==6945==    at 0x57BF32C: vfprintf (in /lib64/libc-2.26.so)
    30 ==6945==    by 0x57C69B5: printf (in /lib64/libc-2.26.so)
    31 ==6945==    by 0x4005D3: main (in /home/nosoul/DEV/test/a.out)
    32 ==6945== 
    33 0
    34 ==6945== Invalid read of size 4
    35 ==6945==    at 0x4005DC: main (in /home/nosoul/DEV/test/a.out)
    36 ==6945==  Address 0x5b38c90 is 4 bytes after a block of size 12 alloc'd
    37 ==6945==    at 0x4C2F06F: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    38 ==6945==    by 0x4005B8: main (in /home/nosoul/DEV/test/a.out)
    39 ==6945== 
    40 0
    41 ==6945== 
    42 ==6945== HEAP SUMMARY:
    43 ==6945==     in use at exit: 12 bytes in 1 blocks
    44 ==6945==   total heap usage: 3 allocs, 2 frees, 73,740 bytes allocated
    45 ==6945== 
    46 ==6945== LEAK SUMMARY:
    47 ==6945==    definitely lost: 12 bytes in 1 blocks
    48 ==6945==    indirectly lost: 0 bytes in 0 blocks
    49 ==6945==      possibly lost: 0 bytes in 0 blocks
    50 ==6945==    still reachable: 0 bytes in 0 blocks
    51 ==6945==         suppressed: 0 bytes in 0 blocks
    52 ==6945== Rerun with --leak-check=full to see details of leaked memory
    53 ==6945== 
    54 ==6945== Use --track-origins=yes to see where uninitialised values come from
    55 ==6945== For lists of detected and suppressed errors, rerun with: -s
    56 ==6945== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)

    检测结果先看“HEAP SUMMARY”开始往后的内容。参考第52行以及第54的提示,因此我们运行

    valgrind --track-origins=yes --leak-check=full ./a.out

    输出如下

     1 ==7080== Memcheck, a memory error detector
     2 ==7080== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
     3 ==7080== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
     4 ==7080== Command: ./a.out
     5 ==7080== 
     6 ==7080== Conditional jump or move depends on uninitialised value(s)
     7 ==7080==    at 0x57BF132: vfprintf (in /lib64/libc-2.26.so)
     8 ==7080==    by 0x57C69B5: printf (in /lib64/libc-2.26.so)
     9 ==7080==    by 0x4005D3: main (test.cpp:6)
    10 ==7080==  Uninitialised value was created by a heap allocation
    11 ==7080==    at 0x4C2F06F: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    12 ==7080==    by 0x4005B8: main (test.cpp:5)
    13 ==7080== 
    14 ==7080== Use of uninitialised value of size 8
    15 ==7080==    at 0x57BAF3B: _itoa_word (in /lib64/libc-2.26.so)
    16 ==7080==    by 0x57BE820: vfprintf (in /lib64/libc-2.26.so)
    17 ==7080==    by 0x57C69B5: printf (in /lib64/libc-2.26.so)
    18 ==7080==    by 0x4005D3: main (test.cpp:6)
    19 ==7080==  Uninitialised value was created by a heap allocation
    20 ==7080==    at 0x4C2F06F: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    21 ==7080==    by 0x4005B8: main (test.cpp:5)
    22 ==7080== 
    23 ==7080== Conditional jump or move depends on uninitialised value(s)
    24 ==7080==    at 0x57BAF45: _itoa_word (in /lib64/libc-2.26.so)
    25 ==7080==    by 0x57BE820: vfprintf (in /lib64/libc-2.26.so)
    26 ==7080==    by 0x57C69B5: printf (in /lib64/libc-2.26.so)
    27 ==7080==    by 0x4005D3: main (test.cpp:6)
    28 ==7080==  Uninitialised value was created by a heap allocation
    29 ==7080==    at 0x4C2F06F: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    30 ==7080==    by 0x4005B8: main (test.cpp:5)
    31 ==7080== 
    32 ==7080== Conditional jump or move depends on uninitialised value(s)
    33 ==7080==    at 0x57BE8D8: vfprintf (in /lib64/libc-2.26.so)
    34 ==7080==    by 0x57C69B5: printf (in /lib64/libc-2.26.so)
    35 ==7080==    by 0x4005D3: main (test.cpp:6)
    36 ==7080==  Uninitialised value was created by a heap allocation
    37 ==7080==    at 0x4C2F06F: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    38 ==7080==    by 0x4005B8: main (test.cpp:5)
    39 ==7080== 
    40 ==7080== Conditional jump or move depends on uninitialised value(s)
    41 ==7080==    at 0x57BF32C: vfprintf (in /lib64/libc-2.26.so)
    42 ==7080==    by 0x57C69B5: printf (in /lib64/libc-2.26.so)
    43 ==7080==    by 0x4005D3: main (test.cpp:6)
    44 ==7080==  Uninitialised value was created by a heap allocation
    45 ==7080==    at 0x4C2F06F: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    46 ==7080==    by 0x4005B8: main (test.cpp:5)
    47 ==7080== 
    48 0
    49 ==7080== Invalid read of size 4
    50 ==7080==    at 0x4005DC: main (test.cpp:7)
    51 ==7080==  Address 0x5b38c90 is 4 bytes after a block of size 12 alloc'd
    52 ==7080==    at 0x4C2F06F: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    53 ==7080==    by 0x4005B8: main (test.cpp:5)
    54 ==7080== 
    55 0
    56 ==7080== 
    57 ==7080== HEAP SUMMARY:
    58 ==7080==     in use at exit: 12 bytes in 1 blocks
    59 ==7080==   total heap usage: 3 allocs, 2 frees, 73,740 bytes allocated
    60 ==7080== 
    61 ==7080== 12 bytes in 1 blocks are definitely lost in loss record 1 of 1
    62 ==7080==    at 0x4C2F06F: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    63 ==7080==    by 0x4005B8: main (test.cpp:5)
    64 ==7080== 
    65 ==7080== LEAK SUMMARY:
    66 ==7080==    definitely lost: 12 bytes in 1 blocks
    67 ==7080==    indirectly lost: 0 bytes in 0 blocks
    68 ==7080==      possibly lost: 0 bytes in 0 blocks
    69 ==7080==    still reachable: 0 bytes in 0 blocks
    70 ==7080==         suppressed: 0 bytes in 0 blocks
    71 ==7080== 
    72 ==7080== For lists of detected and suppressed errors, rerun with: -s
    73 ==7080== ERROR SUMMARY: 7 errors from 7 contexts (suppressed: 0 from 0)

    第6行访问了未初始化的变量的相关检测如下(1个问题有时会多次检测出来)

    ==7080== Conditional jump or move depends on uninitialised value(s)
    ==7080==    at 0x57BF32C: vfprintf (in /lib64/libc-2.26.so)
    ==7080==    by 0x57C69B5: printf (in /lib64/libc-2.26.so)
    ==7080==    by 0x4005D3: main (test.cpp:6)
    ==7080==  Uninitialised value was created by a heap allocation
    ==7080==    at 0x4C2F06F: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==7080==    by 0x4005B8: main (test.cpp:5)

    第7行访问了非法地址的检测如下

    ==7080== Invalid read of size 4
    ==7080==    at 0x4005DC: main (test.cpp:7)
    ==7080==  Address 0x5b38c90 is 4 bytes after a block of size 12 alloc'd
    ==7080==    at 0x4C2F06F: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==7080==    by 0x4005B8: main (test.cpp:5)

    第5行申请的内存未释放的检测如下

    ==7080== 12 bytes in 1 blocks are definitely lost in loss record 1 of 1
    ==7080==    at 0x4C2F06F: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==7080==    by 0x4005B8: main (test.cpp:5)

    将bug都修复了,再次运行检测工具,输出如下

    ==7313== Memcheck, a memory error detector
    ==7313== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==7313== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
    ==7313== Command: ./a.out
    ==7313== 
    0
    ==7313== 
    ==7313== HEAP SUMMARY:
    ==7313==     in use at exit: 0 bytes in 0 blocks
    ==7313==   total heap usage: 3 allocs, 3 frees, 73,740 bytes allocated
    ==7313== 
    ==7313== All heap blocks were freed -- no leaks are possible
    ==7313== 
    ==7313== For lists of detected and suppressed errors, rerun with: -s
    ==7313== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

    参考网址

  • 相关阅读:
    ie6支持最小高度
    jquery的css详解(二)
    jquery的curCSS方法
    jquery的css详解(一)
    Javascript中的Cookie操作
    C#和Javascript中 正则表达式使用的总结
    SQL JOIN
    C# 委托的”四步走“
    C# 知识笔记
    Jquery学习资源地址
  • 原文地址:https://www.cnblogs.com/NoSoul/p/13356082.html
Copyright © 2020-2023  润新知