C语言中的自由字符指针
Free char pointer in C language
我有以下读取图表的函数。当我在 运行 Valgrind 时出现以下错误:
definitely lost: 1,048,576 bytes in 1 blocks
我正在使用 char * line = malloc(1024 * 1024)
分配 1048576 个字节,但最后,我释放了行指针。我在这里做错了什么?
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;
我认为你应该尝试禁用这条线
ssize_t read = getline(&line, &len, fin);
这是一个猜测,但我认为 line
正在被 getline
...
修改
所以如果你 运行 没有它的代码那么你会看到 valgrind
如果那是问题所在。
如果那是答案,那么您可以为 line
分配更小的内存,并用
定义它
char line [100000];
那么你就不会遇到我认为的同样的内存问题...
您误用了 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
中分配了更多的 space — 在这样做之前它没有义务到 free()
行。
ssize_t getline(char **restrict lineptr, size_t *restrict n,
FILE *restrict stream);
The application shall ensure that *lineptr
is a valid argument that could be passed to the free()
function. If *n
is non-zero, the application shall ensure that *lineptr
either points to an object of size at least *n
bytes, or is a null pointer.
您的代码满足“*lineptr
是可以传递给 free()
的有效参数”标准;但是您将 *n
设置为零,因此第二个条件不相关。由于 *n
表示 "there is no memory allocated yet",它将忽略 *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 的 space,除非我知道它会全部被使用。
请注意,对于空指针和零长度,getline()
通常会分配 space,即使文件为空,它也会立即 returns -1
。您应该采取措施释放它。由于 line
为空,即使 getline()
不分配 space,line
也可以安全地传递给 free()
。
如果编译正确(使用-g
选项编译和link),Valgrind会告诉您哪一行分配了泄漏的内存。如果你没有得到这些信息,你就是在滥用 Valgrind(或者,至少,没有充分利用它——如果你愿意,它可以告诉你更多)。
我有以下读取图表的函数。当我在 运行 Valgrind 时出现以下错误:
definitely lost: 1,048,576 bytes in 1 blocks
我正在使用 char * line = malloc(1024 * 1024)
分配 1048576 个字节,但最后,我释放了行指针。我在这里做错了什么?
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;
我认为你应该尝试禁用这条线
ssize_t read = getline(&line, &len, fin);
这是一个猜测,但我认为 line
正在被 getline
...
所以如果你 运行 没有它的代码那么你会看到 valgrind
如果那是问题所在。
如果那是答案,那么您可以为 line
分配更小的内存,并用
char line [100000];
那么你就不会遇到我认为的同样的内存问题...
您误用了 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
中分配了更多的 space — 在这样做之前它没有义务到 free()
行。
ssize_t getline(char **restrict lineptr, size_t *restrict n, FILE *restrict stream);
The application shall ensure that
*lineptr
is a valid argument that could be passed to thefree()
function. If*n
is non-zero, the application shall ensure that*lineptr
either points to an object of size at least*n
bytes, or is a null pointer.
您的代码满足“*lineptr
是可以传递给 free()
的有效参数”标准;但是您将 *n
设置为零,因此第二个条件不相关。由于 *n
表示 "there is no memory allocated yet",它将忽略 *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 的 space,除非我知道它会全部被使用。
请注意,对于空指针和零长度,getline()
通常会分配 space,即使文件为空,它也会立即 returns -1
。您应该采取措施释放它。由于 line
为空,即使 getline()
不分配 space,line
也可以安全地传递给 free()
。
如果编译正确(使用-g
选项编译和link),Valgrind会告诉您哪一行分配了泄漏的内存。如果你没有得到这些信息,你就是在滥用 Valgrind(或者,至少,没有充分利用它——如果你愿意,它可以告诉你更多)。