• Valgrind 快速入门


    1. 介绍

    Valgrind工具组提供了一套调试与分析错误的工具包,能够帮助你的程序工作的更加准确,更加快速。这些工具之中最有名的是Memcheck。它能够识别很多C或者C++程序中内存相关的错误,这些错误会导致程序崩溃或者出现不可预知的行为。

    接下来会以最短的篇幅告诉你如何使用Memcheck来识别你写的程序中的内存错误。你可以从用户手册中获取Memcheck的完整文档以及其他工具的使用说明。

    2. 准备你的程序

    在编译程序时开启-g选项来引入调试信息,这样Memcheck的错误信息中能够准确的显示问题代码的序号。如果你能够容忍一些性能损失,请使用-O0选项来编译程序.使用-O1方式来编译程序错误信息可能会不准确,虽然大体而言在使用-O1方式编译的程序上使用Memcheck没有问题,而且相比-O0方式编译的程序而言性能大为提升.不推荐使用-O2或者更高级别来编译程序,因为Memcheck偶尔会误报值未初始化的错误.

    3.在Memcheck下运行你的程序

    如果你的程序按照以下方式运行:

    myprog arg1 arg2

    请使用下述命令来执行内存检查:

    valgrind --leak-check=yes myprog arg1 arg2

    Memcheck是默认的工具,开启--leak-check选项会启动内存泄露检查.

    你的程序会比正常运行慢很多(大概20到30倍),并且会使用更多的内存.Memcheck会记录检测到的内存错误和内存泄露信息.

    4.解释Memcheck的输出信息

    这是我们的用于示例的C程序代码,其文件名为a.c,这段代码中有一个内存错误和内存泄露问题.

    #include <stdio.h>
    
    void f(){
    	int * x = malloc(10 * sizeof(int));
    	x[10] = 0;  //problem 1: heap block overrun
    				//problem 2: memory leak -- x not freed
    }
    int main(){
    	f();
    	return 0;
    }
    

    下面是使用上述C代码生成程序的makefile文件.

    example:example.o
    	gcc -o example example.o
    
    example.o:a.c
    	gcc -c -O0 -g -Wall a.c -o example.o
    
    .PHONY:clean
    clean:
    	-rm -rf *.o example
    

    使用下述命令检查程序中的内存错误:

    valgrind --leak-check=yes ./example

    大多数的错误信息和下面的一致,下面展示了内存越界的错误:

    ==5753== Invalid write of size 4
    ==5753==    at 0x40053B: f (a.c:5)
    ==5753==    by 0x40054B: main (a.c:9)
    ==5753==  Address 0x51fc068 is 0 bytes after a block of size 40 alloc'd
    ==5753==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==5753==    by 0x40052E: f (a.c:4)
    ==5753==    by 0x40054B: main (a.c:9)
    

    注意:

    • 每一个错误有很多信息, 请认真阅读
    • 5732是进程ID,这一般不重要
    • 第一行Invalid write告诉你出现了哪一种错误.因为内存泄露,程序向本不能访问的内存进行了写入操作.
    • 在第一行之后紧跟的堆栈轨迹信息告诉你问题出现的位置. 堆栈轨迹信息可能会非常大,非常令人迷惑,特别是当你使用C++ STL的时候.推荐按照从下到上的顺序进行阅读.如果堆栈轨迹信息不够,可以使用--num-callers选项来扩充堆栈轨迹信息.
    • 代码地址(例如:0x40054B) 一般不重要,但是有时在追踪神秘的bug时会很有用.
    • 一些错误信息有第二个部分描述了涉及到的内存地址.这一段表明了写入的内存正好在malloc函数分配的内存的后面,对应代码中的第9行.

    推荐按照提示的顺序来修复错误.因为后面的错误可能因为前面的错误导致.否则你会觉得Memcheck不好用.

    内存泄露信息如下所示:

    ==5753== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
    ==5753==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==5753==    by 0x40052E: f (a.c:4)
    ==5753==    by 0x40054B: main (a.c:9)
    

    堆栈追踪信息告诉你泄露的内存在哪里分配的.Memcheck不能告诉你为什么内存会泄露.

    有几种不同的内存泄露方式,其中最重要的两种类别是:

    • "definitely lost": 你的程序泄露了内存,请修复这个错误.
    • "probably lost": 你的程序泄露了内存,除非你在"玩弄"指针(例如移动指针到分配的内存块的中间位置)

    如果你不理解错误信息,请查询用户手册中关于Memcheck错误信息的说明,其中举例说明了Memcheck产生的所有类型的错误信息.

    5.警告

    Memcheck并不完美,它偶尔会误报,有些机制可以抑制这些误报.(请参考用户手册中的减少出错章节).然而,他在99%的情况下都不会出错,所以你需要谨慎地忽略它报告的错误信息.毕竟,你也不会忽略编译器的报警信息.抑制机制对于你不能修改的库代码也有用.默认的抑制会影响库代码中的内存错误.

    Memcheck不能够侦测你程序中的所有内存错误.比如,他不能识别越界读,或者对分配到栈区的数组的越界写入.但是它能够识别能导致你程序崩溃的大多数错误.

    尝试使你的程序更加清晰,这样Memcheck检测不出错误.当你达到这种状态,你会更容易发现对程序的哪些修改导致Memcheck报告了新的错误.数年的Memcheck使用经验说明,大型程序也能够使用Memcheck. 比如KDE,Firefox等.

    6.更多信息

    请查询 Valgrind FAQ Valgrind User Manual.使用--tool选项可以使用Valgrind中的其他工具.

  • 相关阅读:
    ubuntu的php7与apache2的环境搭建
    git服务器搭建post-receive 钩子部署服务端代码
    node redis安装与使用
    微信小程序坑集
    微信小程序登录
    mobx react
    react-native-router-flux 下部导航
    java
    java
    java
  • 原文地址:https://www.cnblogs.com/zhoudayang/p/6110360.html
Copyright © 2020-2023  润新知