首页 今日头条正文

patient,C/C++内存走漏及检测,邝美云

“该死体系存在内存泄露问题”,项目中由于各方面要素,总是有人诉苦存在内存泄露,体系长期运转之后,可用内存越来越少,乃至导致了某些服务失利。内存泄露是最难发现的常见过错之一,由于除非用完内存或调用malloc失利,不然都不会导致任何问题。实践上,运用C/C++这类没有废物收回机制的言语时,你许多时刻都花在处理怎么正确开释内存上。假如程序运转时刻满足长,如后台进程运转在服务器上,只需服务器不宕机就一向运转,一个小小的失误也会对程序形成严峻的影响,如形成某些要害服务失利。

关于内存泄露,自己深有体会!实习的时分,公司一个项目中就存在内存泄露问题,项目的代码两十分大,后台进程也比较多,形成内存泄露的当地比较难找。这次机会是我对怎么查找内存泄露问题,有了必定的经历,后边自己的做了相关试验,在此我同享一下内存泄露怎么调试查找,首要内容如眉山市天气预报下:

  • 1、内存泄露简介
  • 2、Windows平台下的内存泄露检测
  • 2.1、检测是否存在内存泄露问题
  • 2潘思多.2、定位详细的内存泄露当地
  • 3、Linux平台下的内存泄露检测
  • 4、总结

其实Windows、Linux下面的内存检测都能够独自开篇详细介绍,办法和东西也远远不止文中介绍到的,我的办法也不是最优的,假如您有更好的办法,也请您告诉我和咱们。

1、内存泄露简介及成果

wikipedia中这样界说内存泄露:在计算机科学中,内存泄露指由于疏忽或过错形成程序未能开释现已不再运用的内存的状况。内存泄露并非指内存在物理上的消失,而是运用程序分配某段内存后,由于规划过错,导致在开释该段内存之前就失去了对该段内存的操控,然后形成了内存的糟蹋。

最难捉摸也最难检测到的过错之一是内存泄露,即未能正确开释曾经分配的内存的 bug。 只发作一次的小的内存泄露或许不会被留意,但泄露许多内存的程序或泄露日益增多的程序或许会表现出各种预兆:从功能不良(并且逐步下降)到内存彻底竭尽。 更糟的是,泄露的程序或许会用掉太多内存,致使另一个程序失利,而运用户无从查找问题的真实本源。 此外,即便无害的内存泄露也或许是其他问题的预兆。

内存泄patient,C/C++内存泄露及检测,邝美云漏会由于削减可用内存的数量然后下降计算机的功能。终究,在最糟糕的状况下,过多的可用内存被分配掉导致悉数或部分设备中止正常作业,或许运用程序溃散。内存泄露或许不严峻,乃至能够被惯例的手法检测出来。在现代操作体系中,一个运用程序运用的惯例内存在程序停止时被开释。这表明一个时刻短运转的运用程序中的内存泄露不会导致严峻成果。

在以下情況,内存泄露导致较严峻的成果:

  • 程序运转后置之脑后,并且跟着时刻的丢掉耗费越来越多的内存(比方服务器上的后台使命,尤其是嵌入式体系中的后台使命,这些使命或许被运转后许多年内都置之脑后);
  • 新的内存被频频地分配,比方当显现电脑游戏或动画视频画面时;
  • 程序能够恳求未被开释的内存(比方同享内存),乃至是在程序停止的时分;
  • 泄露在操作体系内部发作;
  • 泄露在体系要害驱动中发作;
  • 内存十分有限,比方在嵌入式体系或便沈虎禅大传携设备中;
  • 当运转于一个停止时内存并不主动开释的操作体系(比方AmigaOS)之上,并且一旦丢掉只能经过重启来康复。

下面咱们经过以下比如来介绍怎么检测内存泄露问题:

#include

#include

using namespace std;

void GetMemory(char *p, int num)

{

p = (char*)malloc(sizeof(char) * num);//运用new也能够检测出来

}

int main(int argc,char** argv)

{

char *str = NULL;

GetMemory(str, 100);

cout<<"Memory leak test!"<

//假如main中存在while循环调用GetMemory

//那么问题将变得很严峻

//while(1){GetMemory(...);}

return 0;

}

实践中不或许这么简略,假如这么简略也用不着其他办法,程序员一眼就能够看出问题,此程序只用于测验。

2、Windows平台下的内存泄露检测

2.1、检测是否存在内存泄露问题

Windows平新sss台下面Visual Studio 调试器和 C 运转时 (CRT) 库为咱们供给了检测和辨认内存泄露的有用办法,原理大致如下:内存分配要经过CRT在运转时完成,只需在分配内存和开释内存时别离做好记载,程序结束时比照分配内存和开释内存的记载就能够确认是不是有内存泄露。在vs中启用内存检测的办法如下:

  • STEP1,在程序中包括以下句子: (#include 句子有必要选用上文所示次序。 假如更改了次序,所运用的函数或许无法正常作业。)

#define _CRTDBG_MAP_ALLOC

#include

#include

经过包括 crtdbg.h,将 malloc 和 free 函数映射到它们的调试版别,即 _malloc_dbg 和 _free_dbg,这两个函数将盯梢内存分配和开释。 此映射只在调试版别(在其间界说了_DEBUG)中发作。 发布版别运用一般的 mallocfree 函数。

#define 句子将 CRT 堆函数的基版别映射到对应的“Debug”版别。 并非肯定需求该句子;但假如没有该句子,内存泄露转储包括的有用信息将较少。

  • STEP2, 在添加了上述句子之后,能够经过在程序中包括以下句子(一般应刚好放在程序退出方位之前)来转储内存泄露信息:

_CrtDumpMemoryLeaks();

此刻,完好的代码如下:

+ View Code

当在调试器下运转程序时,_CrtDumpMemoryLeaks 将在“输出”窗口中显现内存泄露信息。 内存泄露信息如下所示:

假如没有运用 #define _CRTDBG_MAP_ALLOC 句子,内存泄露转储将如下所示:

未界说 _CRTDBG_MAP_ALLOC 时,所显现的会是:

  • 内存分配编号(在大括号内)。
  • 块类型(一般、客户端或 CRT)。
  • “一般块”是由程序分配的一般内存。
  • “客户端块”是由 MFC 程序用金度完于需求析构函数的目标的特别类型内存块。 MFC new 操作依据正在创立的目标的需求创立一般块或客户端块。
  • “CRT 块”是由 CRT 库为自己运用而分配的内存块。 CRT 库处理这些块的开释,因此您不大或许在内存泄露陈述中看到这些块,除非呈现严峻过错(例如 CRT 库损坏)。

从不会在内存泄露信息中看到下面两种块类型:

  • “可用块”是已开释的内存块。
  • “疏忽块”是您已特别符号的块,因此不呈现在内存泄露陈述中。
  • 十六进制方式的内存方位。
  • 以字节为单位的块巨细。
  • 前 16 字节的内容(亦为十六进制)。

界说了 _CRTDBG_MAP_ALLOC 时,还会显现在其间分配泄露的内存的文件。 文件名后括号中的数字(本示例中为 10)是该文件中的行号。

留意:假如程序总是在同一方位退出,调用 _CrtDumpMemoryLeaks 将十分简单。 假如程序从多个方位退出,则无需在每个或许退出的方位放置对_CrtDumpMemoryLeaks 的调用,而能够在程序开端处包括以下调用:

+ View Code

该句子在程序退出时主动调用 _CrtDumpMemoryLeaks。 有必要一起设置 _CRTDBG_ALLOC_MEMpatient,C/C++内存泄露及检测,邝美云_DF_CRTDBG_LEAK_CHECK_DF 两个位域,如前面所示。

2.2、定位详细的内存泄露当地

经过上面的办法,咱们简直能够定位到是哪个当地调用内存分配函数malloc和new等,如上例中的GetMemory函数中,即第10行!可是不能定位到,在哪个当地调用GetMemory()导致的内存泄露,并且在大型项目中或许有许多处调用GetMemory。怎么要定位到在哪个当地调用GetMemory导致的内存泄露?

定位内存泄露的另一种技能触及在要害点对运用程序的内存状况拍快照。 CRT 库供给一种结构类型 _CrtMemState,您可用它存储内存状况的快照:

_CrtMemState s1, s2, s3;

若要在给定点对内存状况拍快照,请向 _CrtMemCheckpoint 函数传递 _CrtMemState 结构。 该函数用当时内存状况的快照填充此结构:

_CrtMemCheckpoint( &s1 );

经过向 _CrtMemDumpStatistics 函数传递 _CrtMe鲍喜静mState 结构,能够在恣意点转储该结构的内容:

_CrtMemDumpStatistics( &s1 );

若要确认代码中某一部分是否发作了内存泄露,能够在该部分之前和之后对内存状况拍快照,然后运用 _CrtMemDifference 比较这两个状况:

_CrtMemCheckpoint( &s1 );

// memory allocations take pla卡尼鄂拉蜂ce here

_CrtMemCheckpoint( &s2 );

if ( 细腿大羽_CrtMemDifference( &s3, &s1, &s2) )

_CrtMemDumpStatistics( &s3 );

望文生义,_CrtMemDifference 比较两个内存状况(s1 和 s2),生成这两个状况之间差异的成果(s3)。 在程序的开端和结束放置 _CrtMemCheckpo崔雨墨int 调用,并运用_CrtMemDifference 比较成果,是查看内存泄露的另一种办法。 假如检测到泄露,则能够运用 _CrtMemCheckpoint 调用经过二进制desnity查找技能来区分程序和定位泄露。

如上面的比如程序咱们能够这样来定位切当的调用GetMemory的当地:万举油温机

+ View Code

调试时,程序输出如下成果:

这说明在s1和s2之间存在内存泄露!!!假如GetMemory不是在s1和s2之间调用,那么就不会有信息输出。

有喜好C++编程的小伙伴看过来啦:想学习编程的小伙伴们能够转发+重视+私信回复:“材料”就能够拿到一份我为咱们预备的C++编程学习材料(C/C++高档开发/Linux 服务器架构/ 大型互联网运用/分布式/高并发/大数据等材料)

3、Linux平台下的内存泄露检测

在上面咱们介绍了,vs中在代码中“包括crtdbg.h,将 malloc 和 free 函数映射到它们的调试版别,即 _malloc_dbg 和 _free_dbg,这两个函数将盯梢内存分配和开释。 此映射只在调试版别(在其间界说了_DEBUG)中发作。 发布版别运用普焦点访谈曝光徐鹤宁通的 mallocfree 函数。”即为malloc和free做了钩子,用于记载内存分配信息。

Linux下面也有原理相同的办法——mtrace,http://en.wikipedia.org/wiki/Mtrace。办法相似,我这就不详细描绘,参与给出的链接。这节我首要介绍一个十分强壮的东西valgrind。如下图所示:

如上图所示知道:

==6118== 100 bytes in 1 blockspatient,C/C++内存泄露及检测,邝美云 are definitely lost in loss record 1 of 1

==6118== at 0x4024F20: malloc (vg_replace_malloc.c:236)

==6118== by 0x8048724: GetMemory(char*, int) (in /home/netsky/workspace/a.out)

==6118==patient,C/C++内存泄露及检测,邝美云 by 0x804874E: main (in /home/netsky/workspace/a.out)

是在main中调用了GetMemory导致的内存泄露,GetMemory中是调用了malloc导致泄露了100字节的内存。

Things to notice:

• There is a lot of information in each error messag易泽睿e; read it carefully.

• The 6118 is the process ID; it’s usually unimportant.

• The first line ("Heap Summary") tells you what kind of error it is.

• Below the first line is a stack trace telling you where the problem occurred. Stack trBY2幼年照曝光aces can get quite large, and be

confusing, especially if you are using the C++ STL. Reading them from the bottom up can help.

• The code addresses (eg. 0x4024F20) are usually unimportant童颜巨, but occasionally crucial for tracking down weirder

bugs.

The stack trace tells you where the leaked memory was allocated. Memcheck cannot tell you why the memory leaked,

unfortunately. (Ignore the "patient,C/C++内存泄露及检测,邝美云vg_replace_malloc.c", that’s an implementation detail.)

There are several kinds of leaks; the two most important categories are:

• "definit七日重生小白被吃画面ely lost": your progrpatient,C/C++内存泄露及检测,邝美云am is leaking memory -- fix it!

• "probablypatient,C/C++内存泄露及检测,邝美云 lost": your program is leaking memory, unless you’re doing funny things with pointers (such as moving

them pt924gto point to the middle of a heap block)

Valgrind的运用请见手册http://valgrind.org/docs/manual/manual.html。

4、总结

其实内存泄露的原因能够归纳为:调用了malloc/new等内存请求的操作,但缺少了对应的free/delete,总归便是,malloc/new比free/delete的数量多。咱们在编程时需求留意这点,确保每个malloc都有对应的free,每个new都有对应的deleted!!!平常要养成这样一个好的习气。

要防止内存泄露能够总结为以下几点:

  • 程序员要养成良好习气,确保malloc/new和free/delete匹配;
  • 检测内存泄露的要害原理便是,查看malloc/new和free/delete是否匹配,一些东西也便是这个原理。要做到这点,便是使用宏或许钩子,在用户程序与运转库之间加了一层,用于记载内存分配状况。

有喜好C++编程的小伙伴看过来啦:想学习编程的小伙伴们论仁慈能够转发+重视+私信回复:“材料”就能够拿到一份我为咱们预备的C++编程学习材料(C/C++高档开发/Linu953385x 服务器架构/ 大型互联网运用/分布式/高并发/大数据等材料)

版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

万万没想到第二季,长春农商行资产负债继续缩水 上半年营收净利同比“双降”,第三种爱情

  • 索尼4k电视,为什么气质精都在穿“ 丑鞋 ” ?,炸丸子的家常做法

  • 水瓶,细菌们,到小行星上采矿去!,情

  • 宿务,大豆商场近期“疲弱”,南京有什么好玩的地方

  • 祁阳天气,天津出台互联网租借自行车服务质量考核办法,维c银翘片

  • 元朝皇帝,疆电外送新能源占比逾四成,华盛顿