Chinaunix

标题: 有一个内存泄漏问题 [打印本页]

作者: BuTa丶潇    时间: 2013-07-25 11:02
标题: 有一个内存泄漏问题
本帖最后由 BuTa丶潇 于 2013-07-25 12:57 编辑

不好意思 我有一个问题,貌似是内存泄漏..
我查了几遍,都没找到问题原因..

代码内容大致:
就是我插入几个元素 然后放到链表里..
最后释放的时候
释放完 再遍历 还是有数据..

代码如下,大概就几十行,可以直接运行看到问题..
麻烦谁帮忙看下哪里出的问题吧..谢谢谢谢...

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


#define MAX_ADDR_LEN        128
#define MAX_LINE_LEN     512
#define pError(x) printf("%s\n",x);
#define tfree(x) { if ( x ) { free(x); x = NULL; } }

//链表结构
typedef struct vCard_unique_name_addr
{
    char name[MAX_LINE_LEN];
    char addr[MAX_ADDR_LEN];
    struct vCard_unique_name_addr* pNext;
}vCard_uni_nam_adr;


//释放
static void uni_name_adr_tmp_listfree(vCard_uni_nam_adr * puni_name_adr)
{
    vCard_uni_nam_adr * pTmpuni_nam_adr_pos = NULL;
    vCard_uni_nam_adr * pTmpuni_nam_adr_next = NULL;
    if(NULL == puni_name_adr)
    {
        return ;
    }
    pTmpuni_nam_adr_pos = puni_name_adr;

        for(;pTmpuni_nam_adr_pos != NULL;pTmpuni_nam_adr_pos = pTmpuni_nam_adr_next){
                pTmpuni_nam_adr_next = pTmpuni_nam_adr_pos->pNext;
                tfree(pTmpuni_nam_adr_pos);
        }
    return;
}

//如果有重复的 那么就忽略,即return 1;
//如果没重复的 那么就追加到链表的最后.
static int check_distinct_nam_adr(vCard_uni_nam_adr ** pTmpuni_nam_adr_head , const char *name, const char * addr){
    vCard_uni_nam_adr * pTmpuni_nam_adr_next = NULL;
    vCard_uni_nam_adr * pTmpuni_nam_adr_pos = NULL;
    pTmpuni_nam_adr_pos = *pTmpuni_nam_adr_head ;

    while(pTmpuni_nam_adr_pos != NULL){
        if( strcmp(pTmpuni_nam_adr_pos->name,name)==0 && strcmp(pTmpuni_nam_adr_pos->addr,addr)==0 ){
            return 1;
        }
        pTmpuni_nam_adr_next = pTmpuni_nam_adr_pos;
        pTmpuni_nam_adr_pos = pTmpuni_nam_adr_pos->pNext;
    }

    pTmpuni_nam_adr_pos = (vCard_uni_nam_adr*)malloc(sizeof(vCard_uni_nam_adr));
    if(NULL == pTmpuni_nam_adr_pos)
    {
        pError("Get memory failure while distinct vcard info");
        uni_name_adr_tmp_listfree(*pTmpuni_nam_adr_head);
    }
    else
    {
        memset(pTmpuni_nam_adr_pos,0,sizeof(vCard_uni_nam_adr));
        pTmpuni_nam_adr_pos->pNext = NULL;
        strcpy(pTmpuni_nam_adr_pos->name,name ? name : "null");
        strcpy(pTmpuni_nam_adr_pos->addr,addr ? addr : "null");
        
        if(NULL == *pTmpuni_nam_adr_head){
            *pTmpuni_nam_adr_head = pTmpuni_nam_adr_pos;
        }
        else{
            pTmpuni_nam_adr_next->pNext = pTmpuni_nam_adr_pos;
        }
    }
    return 0;
}

int main(void){
    vCard_uni_nam_adr * pTmpuni_nam_adr_head = NULL;

    check_distinct_nam_adr(&pTmpuni_nam_adr_head,"nihao","188888");
        check_distinct_nam_adr(&pTmpuni_nam_adr_head,"hello","55555");
        check_distinct_nam_adr(&pTmpuni_nam_adr_head,"nihao","188888");
        check_distinct_nam_adr(&pTmpuni_nam_adr_head,"hello","188888");
        check_distinct_nam_adr(&pTmpuni_nam_adr_head,"qqqq","000000");

    vCard_uni_nam_adr * pp = pTmpuni_nam_adr_head;
    while(pp != NULL){
//        sleep(1);
        printf("name:%s,addr:%s\n",pp->name,pp->addr);
        pp = pp->pNext;
    }
        printf("==================\n");
       
        uni_name_adr_tmp_listfree(pTmpuni_nam_adr_head);
       
        vCard_uni_nam_adr *xp = pTmpuni_nam_adr_head;
    while(xp != NULL){
//        sleep(1);
        printf("name:%s,addr:%s\n",xp->name,xp->addr);
        xp = xp->pNext;
    }

}
作者: pmerofc    时间: 2013-07-25 11:12
提示: 作者被禁止或删除 内容自动屏蔽
作者: lxyscls    时间: 2013-07-25 11:19
valgrind跑一次
作者: BuTa丶潇    时间: 2013-07-25 11:29
回复 2# pmerofc


    这个是我当时想测试下 释放完毕后,他是否还存在数据...

如果正常的话 他应该不会进入到这里..


这个就是我不太理解的地方..我释放完毕了怎么还有数据..

**内存泄漏的问题呢..求赐教..谢谢谢谢...
作者: pmerofc    时间: 2013-07-25 11:48
提示: 作者被禁止或删除 内容自动屏蔽
作者: dxyf1524    时间: 2013-07-25 11:53
我估计你是释放函数的参数传递出了问题,函数传值不传址,释放后要将指针置为空
作者: pmerofc    时间: 2013-07-25 12:33
提示: 作者被禁止或删除 内容自动屏蔽
作者: BuTa丶潇    时间: 2013-07-25 13:24
回复 7# pmerofc


    嗯 你的意思是我访问了已经释放的内容,所以导致出错是吗..

我在释放的时候 释放完毕后,设置指针为NULL,

之后是因为想看下是否释放完全,所以在外面访问的时候,先判断是否为NULL,然后才访问的..正常的话不是不应该进入if条件的吗..

不好意思 有点迷糊...能不能麻烦再详细讲解一下 谢谢谢谢..
作者: pix77    时间: 2013-07-25 13:24
lxyscls 发表于 2013-07-25 11:19
valgrind跑一次

+1                                   
作者: BuTa丶潇    时间: 2013-07-25 13:34
回复 3# lxyscls


    谢谢,我接触c没多久 , 还没用过这个东西..我去网上看下..
作者: pmerofc    时间: 2013-07-25 13:39
提示: 作者被禁止或删除 内容自动屏蔽
作者: BuTa丶潇    时间: 2013-07-25 14:37
回复 11# pmerofc


    嗯 ,第一次的代码确实有访问已经释放的的内容,当时是想测试下为何已经释放并置null了 却还存在数据.. 现在看来 无意义了,所以改了下..

   我不太清楚你说的风格概念..可能命名不太好,还是注释太少...这些我以后注意..

   我先把逻辑再理一遍,然后看下**问题吧...要不以这个思路走下去,我感觉风格还是老样子..谢谢你哈..
作者: pmerofc    时间: 2013-07-25 15:37
提示: 作者被禁止或删除 内容自动屏蔽
作者: j3kljs02398j    时间: 2013-07-25 17:46
lxyscls 发表于 2013-07-25 11:19
valgrind跑一次


+1
三楼已经告诉你了很好的解决方式
作者: dxyf1524    时间: 2013-07-26 08:48
        uni_name_adr_tmp_listfree(pTmpuni_nam_adr_head);
      
        vCard_uni_nam_adr *xp = pTmpuni_nam_adr_head;
问题就是出在这里,uni_name_adr_tmp_listfree(pTmpuni_nam_adr_head);返回后“pTmpuni_nam_adr_head != NULL”
按照你的用法,要么用二级指针,要么释放完将一级指针置为空
作者: BuTa丶潇    时间: 2013-07-26 10:35
回复 15# dxyf1524


    谢谢你..
我重新修改了下代码,

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


#define MAX_ADDR_LEN        128
#define MAX_LINE_LEN     512
#define pError(x) printf("%s\n",x);
#define tfree(x) { if ( x ) { free(x); x = NULL; } }

typedef struct vCard_unique_name_addr
{
    char name[MAX_LINE_LEN];
    char addr[MAX_ADDR_LEN];
    struct vCard_unique_name_addr* pNext;
}vCard_uni_nam_adr;


static void uni_name_adr_tmp_listfree(vCard_uni_nam_adr ** puni_name_adr)
{
    vCard_uni_nam_adr * pTmpuni_nam_adr_pos = NULL;
    vCard_uni_nam_adr * pTmpuni_nam_adr_next = NULL;
    if(NULL == *puni_name_adr)
    {
        return ;
    }
    pTmpuni_nam_adr_pos = *puni_name_adr;

        for(;pTmpuni_nam_adr_pos != NULL;pTmpuni_nam_adr_pos = pTmpuni_nam_adr_next){
                pTmpuni_nam_adr_next = pTmpuni_nam_adr_pos->pNext;
                tfree(pTmpuni_nam_adr_pos);
        }
        *puni_name_adr =NULL;
    return;
}

static int check_distinct_nam_adr(vCard_uni_nam_adr ** pTmpuni_nam_adr_head , const char *name, const char * addr){
    vCard_uni_nam_adr * pTmpuni_nam_adr_next = NULL;
    vCard_uni_nam_adr * pTmpuni_nam_adr_pos = NULL;
    pTmpuni_nam_adr_pos = *pTmpuni_nam_adr_head ;

    while(pTmpuni_nam_adr_pos != NULL){
        if( strcmp(pTmpuni_nam_adr_pos->name,name)==0 && strcmp(pTmpuni_nam_adr_pos->addr,addr)==0 ){
            return 1;
        }
        pTmpuni_nam_adr_next = pTmpuni_nam_adr_pos;
        pTmpuni_nam_adr_pos = pTmpuni_nam_adr_pos->pNext;
    }

    pTmpuni_nam_adr_pos = (vCard_uni_nam_adr*)malloc(sizeof(vCard_uni_nam_adr));
    if(NULL == pTmpuni_nam_adr_pos)
    {
        pError("Get memory failure while distinct vcard info");
        uni_name_adr_tmp_listfree(pTmpuni_nam_adr_head);
    }
    else
    {
        memset(pTmpuni_nam_adr_pos,0,sizeof(vCard_uni_nam_adr));
        pTmpuni_nam_adr_pos->pNext = NULL;
        strcpy(pTmpuni_nam_adr_pos->name,name ? name : "null");
        strcpy(pTmpuni_nam_adr_pos->addr,addr ? addr : "null");
        
        if(NULL == *pTmpuni_nam_adr_head){
            *pTmpuni_nam_adr_head = pTmpuni_nam_adr_pos;
        }
        else{
            pTmpuni_nam_adr_next->pNext = pTmpuni_nam_adr_pos;
        }
    }
    return 0;
}

int main(void){
    vCard_uni_nam_adr * pTmpuni_nam_adr_head = NULL;

    check_distinct_nam_adr(&pTmpuni_nam_adr_head,"nihao","188888");
        check_distinct_nam_adr(&pTmpuni_nam_adr_head,"hello","55555");
        check_distinct_nam_adr(&pTmpuni_nam_adr_head,"nihao","188888");
        check_distinct_nam_adr(&pTmpuni_nam_adr_head,"hello","188888");
        check_distinct_nam_adr(&pTmpuni_nam_adr_head,"qqqq","000000");

    vCard_uni_nam_adr * pp = pTmpuni_nam_adr_head;
    while(pp != NULL){
//        sleep(1);
        printf("name:%s,addr:%s\n",pp->name,pp->addr);
        pp = pp->pNext;
    }
        printf("==================\n");
       
        uni_name_adr_tmp_listfree(&pTmpuni_nam_adr_head);
       
        vCard_uni_nam_adr *xp = pTmpuni_nam_adr_head;
    while(xp != NULL){
//        sleep(1);
        printf("name:%s,addr:%s\n",xp->name,xp->addr);
        xp = xp->pNext;
    }

}


我发现一个问题 应该是在上面标红的地方, 我把pos指向了adr所指向的内容, 但是把pos指向的内容释放了并置null后,  adr这个指针还是指向这个释放后的空间..所以再访问adr的时候,会出现段错误.
因此需要将adr这个指针也置null,这样就不会出错了..

不知道我这样理解的对不对...
作者: linux_c_py_php    时间: 2013-07-26 11:16
就个C语言基础, 自己学把, 讨论什么劲.




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2