c/c++的内存管理一直都是程序猿最头痛的事情,内存越界、数组越界、内存泄漏、内存溢出、野指针、空指针..., 随便一个问题都可能让程序崩溃。而且往往问题的源头都比较隐蔽,让人很难排查出问题的根源所在。

想要解决这个问题,还得从问题的根源入手。valgrind是一个强大的内存管理工具,常用来检测内存泄漏和内存的非法使用,用好了可以很好的从根源上解决c/c++内存管理的问题。

1.valgrind的主要功能

virgrind可以用来检测程序开发中的绝大多数内存,函数、缓存使用、多线程竞争访问内存、堆栈问题,是一个linux下功能非常强大内存检测工具。

1 valgrind工具

valgrind-tool= 最常用的选项。运行valgrind中名为toolname的工具。默认memcheck。

memcheck:这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误问题,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。下面将重点介绍此功能。

callgrind: 主要用来检查程序中函数调用过程中出现的问题。

cachegrind: 主要用来检查程序中缓存使用出现的问题。

helgrind: 主要用来检查多线程程序中出现的竞争问题。

massif: 主要用来检查程序中堆栈使用中出现的问题。

extension: 可以利用core提供的功能,自己编写特定的内存调试工具。

2 valgrind memcheck

2.1memcheck内存检测原理

valid-value表:

对于进程的整个地址空间中的每一个字节(byte),都有与之对应的8个bits,对于CPU的每个寄存器,也有一个与之对应的bit向量。这些bits负责记录该字节或者寄存器值是否具有有效的、已经初始化的值。

valid-Address表:

对于进程整个地址空间中的一个字节(byte),还有与之对应的1bit,负责记录该地址是否能够被读写。

内存检测原理:

当要读写内存中的某个字节时,首先检查这个字节对应的address bit。如果该address bit显示该位置是无效位置,memcheck则报告内存读写错误。valgrind内核相当于一个虚拟的CPU环境,当内存中的某个字节被加载到真实的CPU中时,该字节对应的value bit也被加载到虚拟的CPU环境中,一旦寄存器中的值,被用来产生内存地址,或者该值能够影响程序的输出,则mencheck会检查对应的value bits,如果该值尚未初始化,则会报告使用未初始化内存错误。

2.2 memcheck内存检测

2.2.1 准备源码

创建gdbmem.cpp源码文件,准备待检测的代码如下:

#include

#include

#include

#include

#include

#include

//memory access overflow

char* stringcopy(char* psrc)

{

int len = strlen(psrc) + 1;

char* pdst = (char*)malloc(len);//12

memset(pdst, 0, len * 2);//13

memcpy(pdst, psrc, len*2);//14

return pdst;

}

//array assess overflow

void printarray(int arry[], int arrysize)

{

int i = 0;

for(; i < arrysize; i++)

//for(i = arrysize-1; i >= 0; i--)

{

printf("arry[%d]:%d\n",i, arry[i]);

}

printf("arry[%d]:%d\n",i+1, arry[i+1]);//27

}

//main body

int main(int narg, const char** args)

{

char* pwildptr;

char* pstr = "this is a memory debug program!\n";

int array[10] = {1,2,3,4,5,6,7,8,9,10};

char* ptmp = stringcopy(pstr);//36

//memory leak

char* ptmp2 = (char*)malloc(100);//38

memset(ptmp2, 0, 100);

// memory write overflow

printf(ptmp);//41

// array tip assess overflow

printarray(array, 10);//43

free(ptmp);//44

printf("%p", pwildptr);//45

//wild ptr copy

memcpy(ptmp, ptmp2, 20);//47

printf(ptmp);//48

return 0;

}

2.2.2 编译源码:

$g++ -g -O0 -c gdbmem.cpp#-g:编译带调试信息的obj文件,-O0:不优化

$g++ -o gdbmem gdbmem.o

编译后将在当前目录下生成gdbmem可执行文件。

2.2.3 valgrind内存检测

valgring 对gdbmem进行内存检测

$ valgrind --tool=memcheck --leak-check=full --track-fds=yes ./gdbmem

==10668== Memcheck, a memory error detector

==10668== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.

==10668== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info

==10668== Command: ./gdbmem

==10668==

==10668== Invalid write of size 8

==10668== at 0x4C3453F: memset (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x40075D: stringcopy(char*) (gdbmem.cpp:13)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668== Address 0x5204060 is 32 bytes inside a block of size 33 alloc'd

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668==

==10668== Invalid write of size 1

==10668== at 0x4C34558: memset (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x40075D: stringcopy(char*) (gdbmem.cpp:13)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668== Address 0x5204080 is 16 bytes after a block of size 48 in arena "client"

==10668==

==10668== Invalid write of size 8

==10668== at 0x4C326CB: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400778: stringcopy(char*) (gdbmem.cpp:14)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668== Address 0x5204060 is 32 bytes inside a block of size 33 alloc'd

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668==

==10668== Invalid write of size 2

==10668== at 0x4C32723: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400778: stringcopy(char*) (gdbmem.cpp:14)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668== Address 0x5204080 is 16 bytes after a block of size 48 in arena "client"

==10668==

this is a memory debug program!

arry[0]:1

arry[1]:2

arry[2]:3

arry[3]:4

arry[4]:5

arry[5]:6

arry[6]:7

arry[7]:8

arry[8]:9

arry[9]:10

arry[11]:-623874025

==10668== Conditional jump or move depends on uninitialised value(s)

==10668== at 0x4E8890E: vfprintf (vfprintf.c:1631)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x4008E6: main (gdbmem.cpp:45)

==10668==

==10668== Use of uninitialised value of size 8

==10668== at 0x4E84711: _itoa_word (_itoa.c:180)

==10668== by 0x4E8812C: vfprintf (vfprintf.c:1631)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x4008E6: main (gdbmem.cpp:45)

==10668==

==10668== Conditional jump or move depends on uninitialised value(s)

==10668== at 0x4E84718: _itoa_word (_itoa.c:180)

==10668== by 0x4E8812C: vfprintf (vfprintf.c:1631)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x4008E6: main (gdbmem.cpp:45)

==10668==

==10668== Conditional jump or move depends on uninitialised value(s)

==10668== at 0x4E881AF: vfprintf (vfprintf.c:1631)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x4008E6: main (gdbmem.cpp:45)

==10668==

==10668== Conditional jump or move depends on uninitialised value(s)

==10668== at 0x4E87C59: vfprintf (vfprintf.c:1631)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x4008E6: main (gdbmem.cpp:45)

==10668==

==10668== Conditional jump or move depends on uninitialised value(s)

==10668== at 0x4E87CE2: vfprintf (vfprintf.c:1631)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x4008E6: main (gdbmem.cpp:45)

main函数45行,memcpy(ptmp, ptmp2, 20);读取已经被释放的内存,导致memcheck报错。

==10668== Invalid write of size 8

==10668== at 0x4C326CB: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x4008FE: main (gdbmem.cpp:47)

==10668== Address 0x5204040 is 0 bytes inside a block of size 33 free'd

==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x4008D0: main (gdbmem.cpp:44)

==10668== Block was alloc'd at

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668==

==10668== Invalid write of size 2

==10668== at 0x4C32723: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x4008FE: main (gdbmem.cpp:47)

==10668== Address 0x5204050 is 16 bytes inside a block of size 33 free'd

==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x4008D0: main (gdbmem.cpp:44)

==10668== Block was alloc'd at

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668==

==10668== Invalid read of size 1

==10668== at 0x4ED0760: strchrnul (strchr.S:24)

==10668== by 0x4E87207: __find_specmb (printf-parse.h:108)

==10668== by 0x4E87207: vfprintf (vfprintf.c:1312)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x40090F: main (gdbmem.cpp:48)

==10668== Address 0x5204040 is 0 bytes inside a block of size 33 free'd

==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x4008D0: main (gdbmem.cpp:44)

==10668== Block was alloc'd at

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668==

==10668== Invalid read of size 1

==10668== at 0x4E8741A: vfprintf (vfprintf.c:1324)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x40090F: main (gdbmem.cpp:48)

==10668== Address 0x5204040 is 0 bytes inside a block of size 33 free'd

==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x4008D0: main (gdbmem.cpp:44)

==10668== Block was alloc'd at

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668==

0x40097d==10668==

==10668== FILE DESCRIPTORS: 3 open at exit.

==10668== Open file descriptor 2: /dev/pts/4

==10668==

==10668==

==10668== Open file descriptor 1: /dev/pts/4

==10668==

==10668==

==10668== Open file descriptor 0: /dev/pts/4

==10668==

==10668==

==10668==

==10668== HEAP SUMMARY:

==10668== in use at exit: 100 bytes in 1 blocks

==10668== total heap usage: 3 allocs, 2 frees, 1,157 bytes allocated

==10668==

==10668== 100 bytes in 1 blocks are definitely lost in loss record 1 of 1

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400888: main (gdbmem.cpp:38)

==10668==

==10668== LEAK SUMMARY:

==10668== definitely lost: 100 bytes in 1 blocks

==10668== indirectly lost: 0 bytes in 0 blocks

==10668== possibly lost: 0 bytes in 0 blocks

==10668== still reachable: 0 bytes in 0 blocks

==10668== suppressed: 0 bytes in 0 blocks

==10668==

==10668== For counts of detected and suppressed errors, rerun with: -v

==10668== Use --track-origins=yes to see where uninitialised values come from

==10668== ERROR SUMMARY: 37 errors from 15 contexts (suppressed: 0 from 0)

2.2.3 memcheck检测结果分析

memcheck的LEAK SUMMARY输出结果将内存泄漏分为以下几种情况:

definitely lost:明确地已经泄漏了,因为在程序运行完的时候,没有指针指向它, 指向它的指针在程序中丢失了

indirectly lost:间接丢失。当使用了含有指针成员的类或结构时可能会报这个错误。这类错误无需直接修复,他们总是与”definitely lost”一起出现,只要修复”definitely lost”即可。

possibly lost:发现了一个指向某块内存中部的指针,而不是指向内存块头部。这种指针一般是原先指向内存块头部,后来移动到了内存块的中部,还有可能该指针和该内存根本就没有关系,检测工具只是怀疑有内存泄漏。

still reachable:可以访问,未丢失但也未释放

suppressed:已被解决。出现了内存泄露但系统自动处理了。可以无视这类错误。

内存泄漏概述:

==10668== LEAK SUMMARY:

==10668== definitely lost: 100 bytes in 1 blocks

==10668== indirectly lost: 0 bytes in 0 blocks

==10668== possibly lost: 0 bytes in 0 blocks

==10668== still reachable: 0 bytes in 0 blocks

==10668== suppressed: 0 bytes in 0 blocks

此处只有100个字节的内存泄漏。

==10668== Invalid write of size 8

==10668== at 0x4C3453F: memset (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x40075D: stringcopy(char*) (gdbmem.cpp:13)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668== Address 0x5204060 is 32 bytes inside a block of size 33 alloc'd

根据错误提示,stringcopy 函数13行,即memset(pdst, 0, len 2);申请了len的数据长度,memset的时候却使用了2len的数据长度,内存写溢出了。

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668==

==10668== Invalid write of size 1

==10668== at 0x4C34558: memset (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x40075D: stringcopy(char*) (gdbmem.cpp:13)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668== Address 0x5204080 is 16 bytes after a block of size 48 in arena "client"

stringcopy 函数13行,即memset(pdst, 0, len2);申请了len的数据长度,memset的时候却使用了2len的数据长度,内存写溢出。相同语句的内存写溢出,却报了两个错误,原因笔者目前也还没有弄明白,如果有大虾指点,不胜感激。

==10668==

==10668== Invalid write of size 8

==10668== at 0x4C326CB: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400778: stringcopy(char*) (gdbmem.cpp:14)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668== Address 0x5204060 is 32 bytes inside a block of size 33 alloc'd

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668==

==10668== Invalid write of size 2

==10668== at 0x4C32723: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400778: stringcopy(char*) (gdbmem.cpp:14)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668== Address 0x5204080 is 16 bytes after a block of size 48 in arena "client"

stringcopy 函数13行,即memcpy(pdst, psrc, len2);申请了len的数据长度,memset的时候却使用了2len的数据长度,内存写溢出。

==10668==

this is a memory debug program!

arry[0]:1

arry[1]:2

arry[2]:3

arry[3]:4

arry[4]:5

arry[5]:6

arry[6]:7

arry[7]:8

arry[8]:9

arry[9]:10

arry[11]:-623874025

==10668== Conditional jump or move depends on uninitialised value(s)

==10668== at 0x4E8890E: vfprintf (vfprintf.c:1631)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x4008E6: main (gdbmem.cpp:45)

==10668==

==10668== Use of uninitialised value of size 8

==10668== at 0x4E84711: _itoa_word (_itoa.c:180)

==10668== by 0x4E8812C: vfprintf (vfprintf.c:1631)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x4008E6: main (gdbmem.cpp:45)

==10668==

==10668== Conditional jump or move depends on uninitialised value(s)

==10668== at 0x4E84718: _itoa_word (_itoa.c:180)

==10668== by 0x4E8812C: vfprintf (vfprintf.c:1631)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x4008E6: main (gdbmem.cpp:45)

==10668==

==10668== Conditional jump or move depends on uninitialised value(s)

==10668== at 0x4E881AF: vfprintf (vfprintf.c:1631)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x4008E6: main (gdbmem.cpp:45)

==10668==

==10668== Conditional jump or move depends on uninitialised value(s)

==10668== at 0x4E87C59: vfprintf (vfprintf.c:1631)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x4008E6: main (gdbmem.cpp:45)

==10668==

==10668== Conditional jump or move depends on uninitialised value(s)

==10668== at 0x4E87CE2: vfprintf (vfprintf.c:1631)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x4008E6: main (gdbmem.cpp:45)

main函数45行,printf("%p", pwildptr);读取未初始化的野指针

==10668==

==10668== Invalid write of size 8

==10668== at 0x4C326CB: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x4008FE: main (gdbmem.cpp:47)

==10668== Address 0x5204040 is 0 bytes inside a block of size 33 free'd

==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x4008D0: main (gdbmem.cpp:44)

==10668== Block was alloc'd at

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668==

==10668== Invalid write of size 2

==10668== at 0x4C32723: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x4008FE: main (gdbmem.cpp:47)

==10668== Address 0x5204050 is 16 bytes inside a block of size 33 free'd

==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x4008D0: main (gdbmem.cpp:44)

==10668== Block was alloc'd at

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12)

==10668== by 0x40087A: main (gdbmem.cpp:36)

main函数47行,memcpy(ptmp, ptmp2, 20);写入已经释放的内存

==10668==

==10668== Invalid read of size 1

==10668== at 0x4ED0760: strchrnul (strchr.S:24)

==10668== by 0x4E87207: __find_specmb (printf-parse.h:108)

==10668== by 0x4E87207: vfprintf (vfprintf.c:1312)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x40090F: main (gdbmem.cpp:48)

==10668== Address 0x5204040 is 0 bytes inside a block of size 33 free'd

==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x4008D0: main (gdbmem.cpp:44)

==10668== Block was alloc'd at

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12)

==10668== by 0x40087A: main (gdbmem.cpp:36)

==10668==

==10668== Invalid read of size 1

==10668== at 0x4E8741A: vfprintf (vfprintf.c:1324)

==10668== by 0x4E8F898: printf (printf.c:33)

==10668== by 0x40090F: main (gdbmem.cpp:48)

==10668== Address 0x5204040 is 0 bytes inside a block of size 33 free'd

==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x4008D0: main (gdbmem.cpp:44)

==10668== Block was alloc'd at

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12)

==10668== by 0x40087A: main (gdbmem.cpp:36)

main函数47行,printf(ptmp);写入已经释放的内存

0x40097d==10668==

==10668== FILE DESCRIPTORS: 3 open at exit.

==10668== Open file descriptor 2: /dev/pts/4

==10668==

==10668==

==10668== Open file descriptor 1: /dev/pts/4

==10668==

==10668==

==10668== Open file descriptor 0: /dev/pts/4

==10668==

linux为了实现一切皆文件的设计哲学,不仅将数据抽象成了文件,也将一切操作和资源抽象成了文件,比如说硬件设备,socket,磁盘,进程,线程等。

这样的设计将系统的所有动作都统一起来,实现了对系统的原子化操作,大大降低了维护和操作的难度。

设备描述符,就是描述该文件数据设备的唯一标示,不同类型的文件,文件描述符也不一样,如下所示:

==10668==

==10668==

==10668== HEAP SUMMARY:

==10668== in use at exit: 100 bytes in 1 blocks

==10668== total heap usage: 3 allocs, 2 frees, 1,157 bytes allocated

==10668==

==10668== 100 bytes in 1 blocks are definitely lost in loss record 1 of 1

==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==10668== by 0x400888: main (gdbmem.cpp:38)

==10668==

内存泄漏概述,3次内存分配,两次释放。已经有100个字节的内存已经确定泄漏。泄漏的内存分配于38行,charptmp2 = (char)malloc(100);至此,内存泄漏检测完毕。

valgrind内存检测解析

valgrind对内存读写溢出,读取未初始化的变量、指针、内存能够很好的检测到,但是对于数组越界却无法检测,这是因为memcheck并不对stack和全局数组进行越界检查,所以无法检测出printarray中的内存访问越界。

linux 内存溢出排查_linux下valgrind内存问题排查相关推荐

  1. Java内存溢出异常(下)

    此篇是上一篇文章Java内存溢出异常(上)的续篇,没有看过的同学,可以先看一下上篇.本篇文章将介绍剩余的两个溢出异常:方法区和运行时常量池溢出. 方法区和运行时常量池溢出 这部分为什么会放在一起呢?在 ...

  2. python 内存溢出能捕获吗_Python内存泄漏和内存溢出的解决方案

    一.内存泄漏 像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题. 对于一个用 python 实现的,长期运行的后台服务进程来说,如果内存持续增长,那么很可能是 ...

  3. 【调试手段】linux下valgrind内存泄露检查

    参考文章:http://blog.csdn.net/wzzfeitian/article/details/8567030 文库资料:                                   ...

  4. linux open 头文件_linux下通过共享内存和mmap实现进程间通讯

    前言 最近在学习GNU/Linux内核,看到mmap的时候书上说: mmap/munmap接口函数是用户最常用的两个系统调用接口,无论是在用户程序中分配内存.读写大文件.链接动态库文件,还是多进程间共 ...

  5. linux sleeping进程多_Linux下找出吃内存的方法总结

    linux下查询进程占用的内存方法总结,假设现在有一个「php-cgi」的进程 ,进程id为「25282」.现在想要查询该进程占用的内存大小.linux命令行下有很多的工具进行查看,现总结常见的几种方 ...

  6. 怎么调试内存溢出的c++代码_使用jvisualvm排查一次内存溢出(OOM)过程

    内存溢出在开发中或者线上出现的概率很高,造成的直接原因就是系统运行缓慢,或者直接宕机了. 小编在这里模拟下内存溢出的情况以防患于线上出现内存溢出要如何排查问题.题外话(线上出问题你需要生成一个快照(h ...

  7. Linux运维:CentOS7下查看内存占用

    文章目录 查看主机信息 查看操作系统信息 查看Linux系统版本 查看物理CPU个数和型号 查看单个物理CPU核心数 查看逻辑CPU个数 查看内存信息 查看内存情况 查看内存剩余情况 内存使用排序取前 ...

  8. Java反序列化json内存溢出_fastJson与一起堆内存溢出'血案'

    现象 QA同学反映登录不上服务器 排查问题1–日志级别 查看log,发现玩家登录的时候抛出了一个java.lang.OutOfMemoryError 大概代码是向Redis序列化一个PlayerMir ...

  9. 内存溢出_关于PermGen Space内存溢出解决方案

    内存溢出分为Heap Space和PermGen Space两种异常.正巧的是我这次就碰到了PermGen space异常,为了解决这个异常花了我 半天的时间,所以今天写这个方案就是做一种笔记. 刚开 ...

最新文章

  1. Android APP性能优化
  2. vue+element 后台管理系统(三)树形图
  3. 隐藏input边框(ie6、ie7)
  4. centos 开机启动java_Centos 7将java jar包自定义开机启动服务
  5. android自定义的生命周期,android 自定义控件之ViewGroup生命周期执行步骤(示例代码)...
  6. display image without margin in matlab
  7. 飞信机器人 ld-linux.so.2,基于linux的飞信机器人2010版安装
  8. 国讯之MTK Ralink方案GPIO驱动介绍
  9. matlab二维插值绘制地貌图
  10. 您应该学习SwiftUI,UIKit还是同时学习两者?
  11. Win7 启动 0xc0000034错误 - 解决
  12. 刘夏真的简历中国科学院计算机所,一个中科院,四个985,还有一个志愿留在本校,这个学霸考研宿舍是怎样炼成的?...
  13. mmdetection特征可视化V2
  14. 某电子订单系统升级步骤
  15. Spring Security技术栈开发企业级认证与授权-笔记
  16. 【Linux操作系统基础】第六章 Linux中的进程管理
  17. ViewModel是如何在配置更改后继续留存数据的
  18. 解决swagger几种报错问题
  19. Chromeplus(枫树浏览器):基于谷歌Chrome的双核安全浏览器
  20. 用计算机怎么更改进位制,计算机中的进位制,8421法是怎么转换的啊,求解

热门文章

  1. 一个已经转行一年的程序员的感受
  2. 中国智能制造发展趋势!
  3. Java开源 Web开发框架
  4. goproxy和go modules的初步使用
  5. allegro PCB 检查报告中的Report DangLine以及禁用Antenna vias
  6. Node 之 nvm 下载、安装、使用,以及node 、nrm 的相关使用
  7. 初识Java ~ (二) # Java 中程序的执行流程,(万字长文)特别细~ 可收藏~
  8. GLView基本分析
  9. 一款 ≥28倍变焦的4K高清会议云台摄像机动态功能
  10. Nexys video ftp搭建和传输