码迷,mamicode.com
首页 > 其他好文 > 详细

内存泄漏及简单检测的一种方法

时间:2016-04-29 09:24:36      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:

1.什么是内存泄漏(Memory Leak)? 

   简单地说就是申请了一块内存空间,使用完毕后没有释放掉。它的一般表现方式是程序运行时间越长,占用内存越多,最终用尽全部内存,整个系统崩溃。由程序申请的一块内存,且没有任何一个指针指向它,那么这块内存就泄露了。

2.内存泄漏的危害性

    从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。主要有以下几种表现形式:

1)cpu资源耗尽:估计是机器没有反应了,键盘,鼠标,以及网络等等。这个在windows上经常看见,特别是中了毒。
2)进程id耗尽:没法创建新的进程了,串口或者telnet都没法创建了。
3)硬盘耗尽: 机器要死了,交换内存没法用,日志也没法用了,死是很正常的。

在我们写程序的时候,一般会使用malloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。如果要避免这个问题,还是要从代码上入手,良好的编码习惯和规范,是避免错误的不二法门。

3.如何检测内存泄漏?

第一:良好的编码习惯,尽量在涉及内存的程序段,检测出内存泄露。当程式稳定之后,在来检测内存泄露时,无疑增加了排除的困难和复杂度。使用了内存分配的函数,一旦使用完毕,要记得要使用其相应的函数释放掉。

Heap memory:

malloc\realloc ------ free

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

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

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

MyPointEX *pointArray =new MyPointEX [100];

其删除形式为:

delete []pointArray ;


第二:将分配的内存的指针以链表的形式自行管理,使用完毕之后从链表中删除,程序结束时可检查改链表。

第三:Boost 中的smart pointer。

第四:一些常见的工具插件,如ccmalloc、Dmalloc、Leaky等等。

4.代码示例

    我主要想结合代码讲讲第二个方法,设计思想其实很简单,用到STL中的list。可能有人要问,为什么不用vector呢?
list和vector的区别如下:

vector为存储的对象分配一块连续的地址空间,因此对vector中的元素随机访问效率很高。在vecotor中插入或者删除某个元素,需要将现有元素进行复制,移动。如果vector中存储的对象很大,或者构造函数复杂,则在对现有元素进行拷贝时开销较大,因为拷贝对象要调用拷贝构造函数。对于简单的小对象,vector的效率优于list。vector在每次扩张容量的时候,将容量扩展2倍,这样对于小对象来说,效率是很高的。

list中的对象是离散存储的,随机访问某个元素需要遍历list。在list中插入元素,尤其是在首尾插入元素,效率很高,
只需要改变元素的指针。

vector适用:对象数量变化少,简单对象,随机访问元素频繁

list适用:     对象数量变化大,对象复杂,插入和删除频繁

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <list>

using namespace std;

const int nMaxSize = 26;
struct Node
{    
    int count;   
    Node *next[nMaxSize];
};
Node *root = NULL;
list <Node *> nodeMemory;

void TreeCreate()
{    
    root = (Node *)malloc(sizeof(Node)); 
    for (int i = 0; i < nMaxSize; ++i) 
    {       
        root->next[i] = NULL;   
    }
}

void TreeInsert(char *pStr)
{    
    int i, j, len = strlen(pStr);
    Node *p = root;    
    Node *q = NULL; 
    for (i = 0; i < len; ++i) 
    {        
        int id = pStr[i] - ‘a‘;    
        if (p->next[id] == NULL)
        {          
            q = (Node *)malloc(sizeof(Node)); 
            if(q != NULL)
                nodeMemory.push_back(q);
            q->count = 0;  
            for (j = 0; j < nMaxSize; ++j)
            {            
                q->next[j] = NULL; 
            }         
            p->next[id] = q; 
        }      
        p->next[id]->count++;  
        p = p->next[id];   
    }
}

int TreeQuery(char *pStr)
{   
    int i, len = strlen(pStr); 
    int id = 0;   
    Node *p = root;  
    for (i = 0; i < len; ++i)  
    {        
        id = pStr[i] - ‘a‘;  
        p = p->next[id];      
        if (p == NULL) return 0;  
    }       
    return p->count;
}

void TreeDelete(Node *p)
{   
    if (p == NULL) 
        return ;  
    for (int i = 0; i < nMaxSize; ++i) 
    {      
        TreeDelete(p->next[i]);   
    }    
    nodeMemory.remove(p);
    free(p);
    p = NULL;
}

int main(int argc, char **argv)
{   
    char szBuffer[16]; 
    int res = 0;      
    TreeCreate(); 
    int n = 3;
    while (n)   
    {       
        gets(szBuffer); 
        if (strlen(szBuffer) == 0)
            break;     
        TreeInsert(szBuffer); 
        n--;
    }  
/*    scanf("%s", szBuffer);       
    res = TreeQuery(szBuffer); 
    printf("%d\n", res);  */ 
    for(list<Node *>::iterator it = nodeMemory.begin();it != nodeMemory.end();it++)
    {
        cout<<*it<<endl;
    }
    cout<<nodeMemory.size()<<endl;
    TreeDelete(root);    
    if(nodeMemory.empty())
        cout<<"has delete the tire tree"<<endl;
    cout<<nodeMemory.size()<<endl; 
    system("pause");
    return 0;
}

  

代码很简单,list存储的是指向内存空间的指针,每次malloc之后会把这个分配的内存指针push到list中,而当free之后,list的就会删除相应的内容,如果全释放掉了,则list变为空,从而可以判断使用后的内存是否全部释放掉了?

内存泄漏及简单检测的一种方法

标签:

原文地址:http://www.cnblogs.com/shouce/p/5445020.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!