【发布时间】:2021-09-07 14:53:24
【问题描述】:
我编写了以下函数来读取文本文件的行并将它们保存到全局数组中:
/* maximum number of lines allowed in one source file */
#define MAXSRCLNS 100
char *G_source_lines[MAXSRCLNS]; /* source lines */
/* number of source lines saved into source_ */
size_t G_source_lines_count = 0;
/*
* reads the source file 'path' and puts non-empty lines into the
* array G_source_lines. increments the number of lines
* G_source_lines_count for each line saved.
*/
void read_lines(char *path)
{
FILE *stream;
stream = fopen(path, "r");
if (!stream) {
fprintf(stderr, "can't open source '%s'\n", path);
exit(EXIT_FAILURE);
}
char *lnptr = NULL;
size_t n = 0;
while ((getline(&lnptr, &n, stream) != -1)) {
/* throw away empty lines */
if (!isempty(lnptr)) {
/* assert(("line count too large", G_source_lines_count < MAXSRCLNS)); */
G_source_lines[G_source_lines_count++] = lnptr;
} else {
/* I don't save an empty line in the G_source_lines for later
freeing, so free the allocation right here! */
free(lnptr);
}
lnptr = NULL;
}
/* free the lnptr variable defined and allocated on this stack */
/* don't forget to free it's copies in G_source_lines when done with it */
free(lnptr);
fclose(stream);
}
void free_source_lines(void)
{
for (size_t ln = 0; ln < G_source_lines_count; ++ln)
free(G_source_lines[ln]);
}
我不确定通过保存在lnptr 中的getline 将指向分配内存的指针复制到G_source_lines 中是否有必要释放这些副本,因为free_source_lines 函数在完成G_souce_lines 后应该这样做,或者最后在 read_line 中释放lnptr 一次就足够了吗?
【问题讨论】:
-
是的,你需要在
free_source_lines()释放所有东西。 -
但是
free(lnptr)并没有什么坏处,因为free(NULL)什么也没做。 -
@Barmar 来自 getline 的手册页:
If *lineptr is set to NULL and *n is set 0 before the call, then getline() will allocate a buffer for storing the line. This buffer should be freed by the user program even if getline() failed. -
因此,您可以将
lnptr = NULL;移动到if部分,并完全删除else部分(保留分配的缓冲区)。函数末尾的最终free(lnptr);将释放任何未使用的缓冲区。 -
下一次调用
getline()时,不需要的“空”缓冲区将被重用或重新分配,因此在读取所有行之前无需释放。不过,释放它并没有什么坏处,只要您从不将“已保存”或“已释放”指针值传回getline。