项目中由于各方面因素,总是有人抱怨存在内存泄漏,系统长时间运行之后,可用内存越来越少,甚至导致了某些服务起不来。实际上,使用C/C++这类没有垃圾回收机制的语言时,你很多时间都花在处理如何正确释放内存上。为以后更方便的检测内存泄漏问题,于是学习使用了valgrind来对内存泄漏进行检测。
Valgrind是linux环境下的一款功能齐全的内存调试和性能分析工具集,它包括Memcheck、Callgrind、Cachegrind、Helgrind、Massif等工具。本文旨在介绍Valgrind工具集中的内存检测工具Memcheck的用法,以提高内存错误的查找效率。
下载与安装valgrind
下面带大家介绍一下如何下载与安装:
valgrind官网:
https://www.valgrind.org/
用户也可在valgrind home网站上下载安装包:
https://www.valgrind.org/downloads/
下载完成后:
tar xvf valgrind-3.16.1.tar.bz2
cd valgrind-3.16.1
./configure --prefix=/usr/local/valgrind–指定安装目录
make
make install
或者可以这样下载:
wget https://sourceware.org/pub/valgrind/valgrind-3.16.1.tar.bz2
Valgrind概述
Valgrind具是一个用于调试和分析Linux程序的GPL系统。使用Valgrind的工套件,您可以自动检测许多内存管理和线程错误,使程序更稳定。还可以执行详细的分析以帮助加速程序的执行。下面我们介绍Valgrind工具集中的内存检测工具Memcheck的用法,以提高内存错误的查找效率。
Memcheck
所有对内存的读写都会被检测到,一切对malloc()/free()/new/delete的调用都会被捕获
未释放内存的使用
对释放后内存的读/写
对已分配内存块尾部的读/写
内存泄露
不匹配的使用malloc/new/new[] 和 free/delete/delete[]
重复释放内存
应用实践
下面通过介绍几个范例来说明如何使用Memcheck,示例仅供参考:
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
void test()
{
int *ptr = malloc(sizeof(int)*10);
ptr[10] = 7; // 内存越界
memcpy(ptr +1, ptr, 5); // 踩内存
free(ptr);
free(ptr);// 重复释放
int *p1;
*p1 = 1; // 非法指针
}
int main(int argc ,char *argv[])
{
test();
return 0;
}
编译:
在编译程序的时候打开调试模式(gcc编译器的-g选项)。如果没有调试信息,即使最好的valgrind工具也将中能够猜测特定的代码是属于哪一个函数。打开调试选项进行编译后再用valgrind检查,valgrind将会给你的个详细的报告,比如哪一行代码出现了内存泄漏。
使用Valgrind检查程序Bug:
==4056 == Memcheck, a memory error detector
==4056 == Copyright © 2002-2010, and GNU GPL’d, by Julian Seward et al.
==4056 == Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==4056 == Command: ./tmp
==4056 ==
内存越界:
=4056== Invalid write of size 4
==4056 == at 0x804843F: test (in /home/minger/share/tencent/Memory_Leak/memory_leak_test)
==4056 == by 0x804848D: main (in /home/minger/share/tencent/Memory_Leak/memory_leak_test)
==4056 == Address 0x41a6050 is 0 bytes after a block of size 40 alloc’d
==4056 == at 0x4026864: malloc (vg_replace_malloc.c:236)
==4056 == by 0x8048435: test (in /home/minger/share/tencent/Memory_Leak/memory_leak_test)
==4056 == by 0x804848D: main (in /home/minger/share/tencent/Memory_Leak/memory_leak_test)
踩内存:
==4056 == Source and destination overlap in memcpy(0x41a602c, 0x41a6028, 5)
==4056 == at 0x4027BD6: memcpy (mc_replace_strmem.c:635)
==4056 == by 0x8048461: test (in /home/minger/share/tencent/Memory_Leak/memory_leak_test)
==4056 == by 0x804848D: main (in/home/minger/share/tencent/Memory_Leak/memory_leak_test)
重复释放:
==4056 == Invalid free() / delete / delete[]
==4056 == at 0x4025BF0: free (vg_replace_malloc.c:366)
==4056 == by 0x8048477: test (in /home/minger/share/tencent/Memory_Leak/memory_leak_test)
==4056 == by 0x804848D: main (in /home/minger/share/tencent/Memory_Leak/memory_leak_test)
==4056 == Address 0x41a6028 is 0 bytes inside a block of size 40 free’d
==4056 == at 0x4025BF0: free (vg_replace_malloc.c:366)
==4056 == by 0x804846C: test (in /home/minger/share/tencent/Memory_Leak/memory_leak_test)
==4056 == by 0x804848D: main (in /home/minger/share/tencent/Memory_Leak/memory_leak_test)
非法指针
==4056 == Use of uninitialised value of size 4
==4056 == at 0x804847B: test (in /home/minger/share/tencent/Memory_Leak/memory_leak_test)
==4056 == by 0x804848D: main (in /home/minger/share/tencent/Memory_Leak/memory_leak_test)
从valgrind的检测输出结果看,这几个错误都找了出来。
总结
虽然C/C++是一种非常有用且功能强大的语言,但很难调试。 某些时候可能遇到内存错误。 如果知道出错 ,或者程序一直崩溃,我们可以用gdb去调试。 但是,有时遇到的问题是由于内存错误造成的,但它不出段错误,很多时候,我们不希望海里捞针,在gdb中设置很多断点,逐步盘查。 还有可能会遇到的另一个问题是内存泄漏:在某个地方,调用malloc分配的内存没有调用free来释放。 Valgrind是一个可以帮助解决这些问题的程序。
欢迎关注微信公众号【程序猿编码】,添加本人微信号(17865354792),回复:领取学习资料。或者回复:进入技术交流群。网盘资料有如下: