内存泄漏以及常见的解决方法

您所在的位置:网站首页 net内存泄露 内存泄漏以及常见的解决方法

内存泄漏以及常见的解决方法

2023-09-01 01:36| 来源: 网络整理| 查看: 265

  之所以撰写这篇文章是因为前段时间花费了很大的精力在已经成熟的代码上再去处理memory leak问题。写此的目的是希望我们应该养成良好的编码习惯,尽可能的避免这样的问题,因为当你对着一大片的代码再去处理此类的问题,此时无疑增加了解决的成本和难度。准确的说属于补救措施了。 1. 什么是内存泄漏(memory leak)?

 指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。 

A memory leak is a particular type of unintentional memory consumption by a computer program where the program fails to release memory when no longer needed. This condition is normally the result of a bug in a program that prevents it from freeing up memory that it no longer needs.This term has the potential to be confusing, since memory is not physically lost from the computer. Rather, memory is allocated to a program, and that program subsequently loses the ability to access it due to program logic flaws. 

2. 对于C和C++这种没有Garbage Collection 的语言来讲,我们主要关注两种类型的内存泄漏:

   堆内存泄漏(Heap leak)。对内存指的是程序运行中根据需要分配通过malloc,realloc new等从堆中分配的一块内存,再是完成后必须通过调用对应的 free或者delete 删掉。如果程序的设计的错误导致这部分内存没有被释放,那么此后这块内存将不会被使用,就会产生Heap Leak. 

  系统资源泄露(Resource Leak).主要指程序使用系统分配的资源比如 Bitmap,handle ,SOCKET等没有使用相应的函数释放掉,导致系统资源的浪费,严重可导致系统效能降低,系统运行不稳定。  

3. 如何解决内存泄露?

内存泄露的问题其困难在于1.编译器不能发现这些问题。2.运行时才能捕获到这些错误,这些错误没有明显的症状,时隐时现。3.对于手机等终端开发用户来说,尤为困难。下面从三个方面来解决内存泄露:

第一,良好的编码习惯,尽量在涉及内存的程序段,检测出内存泄露。当程式稳定之后,在来检测内存泄露时,无疑增加了排除的困难和复杂度。

使用了内存分配的函数,要记得要使用其想用的函数释放掉,一旦使用完毕。

Heap memory:

malloc\realloc ------  free

new \new[] ----------  delete \delete[]

GlobalAlloc------------GlobalFree 

要特别注意数组对象的内存泄漏

     MyPointEX *pointArray =new MyPointEX [100];

      其删除形式为:

     delete []pointArray 

Resource Leak :对于系统资源使用之前要仔细看起使用方法,防止错误使用或者忘记释放掉系统资源。

我们看MSDN上一个创建字体的例子:  RECT rect;

HBRUSH hBrush; FONT hFont; hdc = BeginPaint(hWnd, &ps);  hFont = reateFont(48,0,0,0,FW_DONTCARE,FALSE,TRUE,FALSE,DEFAULT_CHARSET,OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY, VARIABLE_PITCH,TEXT("Impact"));

SelectObject(hdc, hFont);  SetRect(&rect, 100,100,700,200);

SetTextColor(hdc, RGB(255,0,0));

DrawText(hdc, TEXT("Drawing Text with Impact"), -1,&rect, DT_NOCLIP);    

DeleteObject(hFont);    EndPaint(hWnd, &ps);

 

如果使用完成时候忘记释放字体,就造成了资源泄漏。 

   对于基于引用计数的系统对象尤其要注意,因为只有其引用计数为0时,该对象才能正确被删除。而其使用过程中有其生成的新的系统资源,使用完毕后,如果没有及时删除,都会影响其引用计数。

 IDNS *m_pDns//define a DNS object.

   If(NULL == m_pDns)

{     IEnv_CreateInstance (m_pEnv,AEECLSID_DNS,(void **) (&m_pDns))

  }

If(m_pDns) {

    Char szbuff[256];

    IDNS_AddQuestions(M_pDns,AEEDNSTYPE_A,ADDDNSCLASS_IN,szbuff);

    IDNS_Start(m_pDns,this);

    const AEEDNSResponse * pDnsResponse = NULL;

   IDNS_GetResponse(pMe->m_pDns, &pDnsResponse);

…………………………………………………………

…………………………………………………………..

………………………………………………………..

}

DNS_Release(pMe->m_pDns);//当程序运行到此时,其返回值不是0,是1,其含义是程序已经产生内存泄露了,系统已经有一个由DNS所产生的内核对象没有释放,而当这段代码多次执行之后,内存泄露将不断增加……..

m_pDns=NULL;

  }

看起来很不直观,仔细分析就会发现,对象pDnsResponse是从m_pDns产生新的object,所以m_pDns的引用计数会增加,因此在使用完pDnsResponse,应该release 该对象使其引用计数恢复正常。   对于资源,也可使用RAII,RAII(Resource acquisition is initialization)资源获取即初始化,它是一项很简单的技术,利用C++对象生命周期的概念来控制程序的资源,例如内存,文件句柄,网络连接以及审计追踪(audit trail)等.RAII的基本技术原理很简单.若希望保持对某个重要资源的跟踪,那么创建一个对象,并将资源的生命周期和对象的生命周期相关联.如此一来,就可以利用C++复杂老练的对象管理设施来管理资源.(有待完善) 

例2:

Struct ITypeface *pTypeface;



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3