C++检测和定位内存泄漏的技巧

来源:互联网 发布:乳源县网络问政 编辑:程序博客网 时间:2024/06/06 03:51
在实际开发过程中项目中由于各方面原因,总是有人抱怨存在内存泄漏,系统长时间运行之后,可用内存越来越少,苌至导致了某些服务失败。内存泄漏是最难发现的常见错误之一,因为除非用完内存或调用malloc失败,否则都不会导致任何问题。实际上,使用C/C++这类没有垃圾回收机制t的语言时,在如何正确处理释放内存上会花费很长时间。如果程序运行时间足够长,如后台进程运行在服务器上,只要服务器不宕机就一立运行,一个小小的失误也会对程序造成重大影响,如造
成某些关键服务失败。

wikipedia中这样定义内存泄漏在计算机科学中,内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。最难捉摸也最难检测到的错误之一是内存泄漏,即未能正确释放以前分配的内存的bug。只发生一次小的内存泄漏可能不会被注意,但泄漏大量内存的程序或泄漏日益增多的程序可能会表现出各种征兆从性能不良(并且逐渐降低)到内存完全用尽。更糟糕的是,泄漏的程序可能会用掉太多内存,以致另一个程序失败,而使用户无从查找问题的真正根源。此外,即使无害的内存泄漏也可能是其他问题的征兆。内存泄漏会因为减少可用内存的数量而降低计算机的性能。最终,在最糟糕的情况下,过多的可用内存被分配掉,导致全部或部分设备停止正常工作,或者应用程序

崩溃。内存泄漏可能不严重,移至能够用常规的手段检测出来。在现代操作系统中,一个应用程序使用的常规内存在程序终止时被释放。这表示一个短暂运行的应用程序中的内存泄漏不会导致严重后果。


在以下情下,内存泄漏会导致较严重的后果:
1.工程序运行后置之不理,时间久了消耗的内存越来越多(比如服务器上的后台任务,尤其是嵌入式系统中的后台任务,这些任务运行后可能很多年内都置之不理);

2·新的内存被频繁地分配,比如当显示电脑游戏或动画视频画面时;

3.程序能够请求未被释放的内存(比如共享内存),移至是在程序终止的时候;

4.泄漏在操作系统内部发生,在系统关键驱动中发生;

5.内存非常有限,比如在嵌入式系统设备中;

6.当运行于一个终止时内存并不自动释放的操作系统(比如AmigaOS)之上,而一旦丢失只能通过重庆来恢复;


通过下面这个例子,来介绍如何检测内存泄漏问题
#include «stdlib. h»
#include «iostream»
using namespace std
void GetMemory(char *p,int num)
{
//使用new也能够检测出来
P=(c har *) malloc(sizeof(char*) * num);
}

int main(int arge, char** argv)
{
char *str=NULL;
GetMemory(str, 100);
cout<<"Memory leak test!"<<endl;
//如果main中存在while循环调用GetMemow
//问题将变得很严重
/ /while(1){

//   GetMemory(...)

//} 

return o 
}

但是,实际开发中不可能这么简单,此程序只用于测试。
Windows平台下的内存泄漏检测方法。Windows平台下Visual Studio调试器和C运行时(CRT)库为我们提供了检测和识别内存泄漏的有效方法,原理大致如下内存分配要通过CRT在运行时实现,只要在分配内存和释放内存时分别做好记录工程序结束时对比分配内存和释放内存的记录就可以确定是不是有内存泄漏。在Visual Studio中启用内存检测的方法如下。

STEP1:在程序中包括以下语句:

#define_CRTDBG_MAP_ALLOC

#include<stdlib.h>

#include<crtdbg.h>

说明#include语句必须采用下文所示的顺序,如果更改了顺序,所使用的函数可能无法正常工作,

通过在代码中包括crtdbg.h,将malloc和free函数映射到对应调试版本,即_malloc_dbg吕和free_dbg中,这两个函数将跟踪内存分配和释放。此映射只在调试版(当定义_DEBUG时)中发生,发布版使用普通的malloc和free函数。

#define语词将CRT堆函数的基版本映射到对应的。Debug。版本,并非绝对需要该语词但如果没有该语词,内存泄漏转储包含的有用信息将较少。

STEP2:在添加了上述语句之后,可以通过在程序中包括下述语(通常应恰好放在程序退出位置之前)来转储内存泄漏信息:
_CrtDumpMemowLeaJcso
按照上面的步骤进行,完整的代码应该是这样的

#define_CRTDBG_MAP_ALLOC
#include <stdlib. h>
#include <crtdbg. h>
#include <iostream>
using namespace std;
void GetMemory(char * p, int num)
{
p=(c har *) malloc (sizeof(char) * num);
}
int maintint arge, char** argv)
{
char *str=NULL;
GetMemory(str, 100);
cout<<"Memory leak test!"<<endl;
_CrtDumpMemoryLeaks();
return 0;
}

当在调试器下运行程序时,_CrtDumpMemoryLeaks将在"输出"窗口中显示内存泄漏信息。内存泄露信息下所以:

Detected memory leaks!
Dumping objects->
c\users \liuguang \ documentAvisual studio 201o \ projectsMemory \ memory. cpp (14):{1159} normal block at O×008F6598, 1 00 bytes long.
Data<           > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

程序"[4904] Memoly.exe本机"已退出,返回值为0 (0×0)。

0 0
原创粉丝点击