C语言中的自由字符指针

时间:2018-04-22 21:36:53

标签: c pointers malloc free

我有以下功能读入图表。当我运行Valgrind时,我收到以下错误:

char * line = malloc(1024 * 1024)

我使用pr_graph * pr_graph_load( char const * const ifname) { FILE * fin = fopen(ifname, "r"); pr_graph * graph = malloc(sizeof(*graph)); char * line = malloc(1024 * 1024); size_t len = 0; /* Read in graph one vertex at a time. */ for(pr_int v=0; v < graph->nvtxs; ++v) { ssize_t read = getline(&line, &len, fin); if(read == -1) { free(line); fprintf(stderr, "ERROR: premature EOF at line %lu\n", v+1); pr_graph_free(graph); return NULL; } /* Store the beginning of the adjacency list. */ graph->xadj[v] = edge_ptr; /* Check for sinks -- these make pagerank more difficult. */ if(read == 1) { fprintf(stderr, "WARNING: vertex '%lu' is a sink vertex.\n", v+1); continue; } /* Foreach edge in line. */ char * ptr = strtok(line, " "); while(ptr != NULL) { char *end = NULL; pr_int const e_id = strtoull(ptr, &end, 10); /* end of line */ if (ptr == end) { break; } assert(e_id > 0 && e_id <= graph->nvtxs); graph->nbrs[edge_ptr++] = e_id - 1; /* 1 indexed */ ptr = strtok(NULL, " "); } } assert(edge_ptr == graph->nedges); graph->xadj[graph->nvtxs] = graph->nedges; free(line); fclose(fin); return graph; 分配1048576个字节,但最后,我释放了行指针。我在这里做错了什么?

{{1}}

2 个答案:

答案 0 :(得分:4)

您滥用POSIX getline()功能。你有:

char * line = malloc(1024 * 1024);
size_t len = 0;

/* Read in graph one vertex at a time. */
for(pr_int v=0; v < graph->nvtxs; ++v)
{
    ssize_t read = getline(&line, &len, fin);

您告诉getline()分配了零字节,因此它在line中分配了更多空间 - 在此之前没有free()行的义务。

ssize_t getline(char **restrict lineptr, size_t *restrict n,
       FILE *restrict stream);
     

应用程序应确保*lineptr是可以传递给free()函数的有效参数。如果*n非零,则应用程序应确保*lineptr指向大小至少为*n字节的对象,或者为空指针。

您的代码符合'*lineptr是一个有效的参数,可以传递给free()'标准;但是您将*n设置为零,因此第二个条件不相关。由于*n表示“尚未分配内存”,因此会忽略*lineptr中的值。

你应该使用其中一种:

char * line = 0;
size_t len = 0;

/* Read in graph one vertex at a time. */
for(pr_int v=0; v < graph->nvtxs; ++v)
{
    ssize_t read = getline(&line, &len, fin);

或:

size_t len = 1024 * 1024;
char * line = malloc(size);

/* Read in graph one vertex at a time. */
for(pr_int v=0; v < graph->nvtxs; ++v)
{
    ssize_t read = getline(&line, &len, fin);

要么工作。我可能会使用空缓冲区 - 我不会经常预先分配1 MiB的空间,除非我知道它将被全部使用。

请注意,使用空指针和零长度,getline()通常会分配空间,即使文件为空并且它立即返回-1。你应该采取措施来解放它。由于line为空,即使getline()未分配空格,line也可以安全地传递给free()

如果您正在正确编译(使用-g选项编译链接),Valgrind将告诉您哪个行分配了泄漏的内存。如果你没有得到这些信息,你就会误用Valgrind(或者,至少使用它不足 - 如果你让它,它可以告诉你更多)。

答案 1 :(得分:0)

我认为您应该尝试禁用此行

ssize_t read = getline(&line, &len, fin);

这是猜测,但我认为line正在修改getline ...

因此,如果您运行没有它的代码,那么您将看到valgrind,如果这就是问题所在。

如果这是答案,那么你可以为line设置较少的内存并用

定义它
char line [100000];
那么你认为你不会有同样的记忆问题......