结构上的free()无效

时间:2015-12-06 09:33:57

标签: c valgrind free

我从文件中提取信息并将它们插入到结构中。但是,我很难在C中释放这个结构。结构如下:

typedef struct codelist{
    char *content;
    struct codelist *next;
}CodeList;

typedef struct comm{
    CodeList *compile;
    CodeList *test;
} Commands;

这里我在文件info和malloc中读取CodeList和Commands结构

/*opens compile_cmds and test_cmds and puts their contents into a Command. 
Exits with 0 if error is found*/
Commands read_commands(const char *compile_cmds, const char *test_cmds){
    int status = 1;
    FILE *f1, *f2;

    if(compile_cmds == NULL || test_cmds == NULL)
        status = 0;
    f1 = fopen(test_cmds, "r");
    f2 = fopen(compile_cmds, "r");

    /*checks if compile_cmds and test_cmds are openable files*/
    if(f1 == NULL || f2 == NULL){
        status = 0;
    }
    fclose(f1);
    fclose(f2);


    /*create dummy headers for compile and test lists*/
    if(status != 0){
        Commands *ans = malloc(sizeof(Commands));
        if(ans != NULL){

            ans->compile = helpread(compile_cmds);
            ans->test = helpread(test_cmds);
            return *ans;
        }
    }
    exit(0);
}

/*takes info out of filename and puts it into a linked list of content
return content*/
CodeList* helpread(const char *filename){
   char curr[256];
    FILE *f;
    f = fopen(filename, "r");
    CodeList *code = malloc(sizeof(CodeList));
    if(code !=NULL && f != NULL){
        code->content = NULL;

        while(fgets(curr, 256, f)){
            CodeList *new = malloc(sizeof(CodeList));
            if(new == NULL)
                break;
            new->content = malloc(sizeof(char)*(strlen(curr)+1));
            if(new->content == NULL)
                break;
            strcpy(new->content, curr);
            new->next = NULL;
            code->next = new;
            code = new;
        }
    }
    fclose(f);
    return code;
}

在我完成它们之后,我清除这些结构,以便使用的内存应为0。 读命令运行良好,清除命令不是什么。虽然我能够释放二级结构,但释放实际的Commands结构会在valgrind中给出一个无效的free()。有人可以帮我解决这个问题吗?

/*clears CodeList
returns number of elements that were in CodeList*/
int helpclear(CodeList *code){
    int ans = 0;
    CodeList *prev;

    while(code !=NULL){
        prev = code;
        code = code->next;
        free(prev->content);
        free(prev);
        ans++;
   }
   return ans;
}


void clear_commands(Commands *commands){
    printf("enter clear_commands\n");
    if(commands !=NULL){
        helpclear(commands->test);
        helpclear(commands->compile);
        free(commands);
    }
    printf("done freeing test and compile\n");

   printf("end clear_commands\n");
}

此外,这是valgrind的结果:

==17133== Invalid free() / delete / delete[] / realloc()
==17133==    at 0x4C27430: free (vg_replace_malloc.c:446)
==17133==    by 0x400E50: ??? (in       /afs/glue.umd.edu/class/fall2015/cmsc/216/0101/student-cmsc216-0403/chan2017/project6/public03.x)
==17133==    by 0x400B8F: ??? (in   /afs/glue.umd.edu/class/fall2015/cmsc/216/0101/student-cmsc216-0403/chan2017/project6/public03.x)
==17133==    by 0x4E4DD5C: (below main) (in /lib64/libc-2.12.so)
==17133==  Address 0x7ff000570 is on thread 1's stack
==17133==

Your code has a memory leak; memory still in use is 304 bytes.
==17133==
==17133== HEAP SUMMARY:
==17133==     in use at exit: 257 bytes in 13 blocks
==17133==   total heap usage: 20 allocs, 8 frees, 2,561 bytes allocated
==17133==
==17133== LEAK SUMMARY:
==17133==    definitely lost: 138 bytes in 5 blocks
==17133==    indirectly lost: 119 bytes in 8 blocks
==17133==      possibly lost: 0 bytes in 0 blocks
==17133==    still reachable: 0 bytes in 0 blocks
==17133==         suppressed: 0 bytes in 0 blocks
==17133== Rerun with --leak-check=full to see details of leaked memory
==17133==
==17133== For counts of detected and suppressed errors, rerun with: -v
==17133== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)

2 个答案:

答案 0 :(得分:4)

read_commands中,未返回malloc缓冲区。正在返回结构的副本(按值)。

Commands *ans = malloc(sizeof(Commands));
if(ans != NULL){
    ....
    return *ans;
}

您尚未显示如何调用read_commands。但无论如何调用它,ans指向的缓冲区都会丢失并且无法释放。所以我假设你在某种程度上解放了你认为动态分配的Commands结构,而实际上并非如此。

应声明read_commands函数返回Commands *而不是Commands,然后它应返回ans而不是*ans

为了更加确定,请说明如何调用read_commands

答案 1 :(得分:0)

对于此处分配的列表中的第一个元素

CodeList* helpread(const char *filename){
  char curr[256];
  FILE *f;
  CodeList *code = malloc(sizeof(CodeList));

...代码错过初始化成员content,所以它指向无处。代码应将其初始化为NULL

此外,代码永远不会对malloc()fopen()的结果进行任何错误检查。

此外,代码不能以安全的方式处理空文件或读错误的情况。