在while循环中使用getline()读取文件是否属于不良编程实践?
问题
如果我需要处理一个几乎每行都包含\n换行符的文件,在while循环中调用getline()读取文件内容是否属于不良编程实践?
我目前的理解是,每遇到一个\n字符就会调用一次getline(),而每次调用都会触发realloc()内存重分配操作,这种实现方式是否效率低下?
提问附示例代码
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char **argv) { FILE *fp = fopen("file.txt", "r"); if (fp == NULL) { perror("Unable to open file: "); exit(1); } char *buffer = NULL; size_t len = 0; ssize_t characters; while ((characters = getline(&buffer, &len, fp)) != -1) { fputs(buffer, stdout); } fclose(fp); free(buffer); buffer = NULL; return 0; }
回答
这种写法不属于不良编程实践,你对getline()的内存分配逻辑存在误解:
getline()并非每次读取一行都会调用realloc(),只有当前传入的缓冲区长度不足以容纳当前行内容时,才会触发扩容。你给出的示例代码中buffer初始为NULL、len初始为0,第一次调用时会分配一块初始大小的内存,后续读取的行只要长度不超过当前缓冲区已分配的长度,就不会产生任何内存重分配开销。- 对于几乎所有普通文本文件——哪怕每行都很短、换行符非常密集——只要行长度没有明显的跳变,
getline()通常只会在最开始的数次调用中完成缓冲区扩容,后续整个读取循环都不会再触发realloc(),额外开销极低,根本不存在效率低下的问题。 - 就算遇到行长度波动较大的极端场景,
getline()的扩容逻辑也是经过glibc等标准库实现反复优化的,一般按2的幂次阶梯扩容,摊还时间复杂度为O(n),和你手动申请大缓冲区、逐块读取的实现效率没有量级差距,同时还自动帮你处理了缓冲区边界判断、换行符识别、内存动态调整等容易写出bug的细节,代码健壮性和可读性反而更好。
只有当你完全不需要按行维度处理内容,只需要对文件做全量无差别的流式拷贝或批量处理时,才需要考虑换用fread()按固定块大小读取——这种替换只是场景适配,为了省掉逐字符判断换行符的少量开销,不是因为getline()本身的实现效率差。
你贴出的示例代码是getline()的标准合规用法,没有任何问题。
内容的提问来源于stack exchange,提问作者rain
相关产品推荐
相关产品推荐

