C语言:使用fgets/fputs逐行复制文件(MAXLINE=4)的缓冲区溢出求助
关于用fgets/fputs逐行复制文件及缓冲区溢出的问题解答
嘿,刚学C语言遇到这种卡壳的情况太正常了,别着急,咱们一步步把问题拆解开~
先纠正你对MAXLINE=4的误解
你以为缓冲区设为4会只返回每行前四个字符,这个理解有点偏差哦。fgets(buf, MAXLINE, fp)里的第二个参数是缓冲区的总字节数,它最多会读取MAXLINE-1个有效字符(因为要留1个字节存字符串结束符\0)。而且fgets的停止规则是:读到换行符、或者达到MAXLINE-1个字符、或者读到文件末尾,三者满足其一就停止。
举个例子:如果源文件里有一行是Hello World!,MAXLINE=4的话,fgets会分多次读取:第一次读Hel+\0,第二次读lo +\0,第三次读Wor+\0,直到把整行内容读完,剩下的字符会留在输入流里,下次调用fgets会接着读。
正确的逐行复制程序(MAXLINE=4)
先给你一个能正常工作的示例代码,你可以对比自己的代码找问题:
#include <stdio.h> #include <stdlib.h> #define MAXLINE 4 // 缓冲区总大小为4,最多存3个有效字符+1个'\0' int main() { FILE *src_file, *dest_file; char buf[MAXLINE]; // 打开源文件和目标文件(记得替换成你自己的文件名) src_file = fopen("source.txt", "r"); dest_file = fopen("destination.txt", "w"); // 检查文件是否成功打开 if (src_file == NULL || dest_file == NULL) { perror("Failed to open file"); exit(EXIT_FAILURE); } // 逐段读取并写入,直到文件末尾 while (fgets(buf, MAXLINE, src_file) != NULL) { fputs(buf, dest_file); } // 别忘了关闭文件 fclose(src_file); fclose(dest_file); return 0; }
运行这个程序后,目标文件会和源文件内容完全一致——哪怕源文件里有超长的行,fgets会自动分段读取,fputs会把这些分段依次写入,最终拼接成完整内容。
如何触发缓冲区溢出?
这里要明确:fgets本身是安全的,它严格限制了读取的字符数,不会让缓冲区溢出。要触发溢出,得用不安全的操作绕开这个限制,比如:
- 使用无长度限制的字符串拷贝函数
#include <stdio.h> #include <string.h> #define MAXLINE 4 int main() { char buf[MAXLINE]; // 故意把长度为10的字符串复制到只有4字节的buf里 strcpy(buf, "HelloWorld"); printf("%s\n", buf); return 0; }
"HelloWorld"加\0一共11个字节,远大于buf的4字节空间,超出的部分会覆盖栈上的其他数据,导致程序崩溃或者出现奇怪的行为。
- 手动越界写入缓冲区
#include <stdio.h> #define MAXLINE 4 int main() { char buf[MAXLINE]; // 手动给buf的第5个位置赋值(buf下标从0开始,合法下标是0-3) buf[4] = 'X'; return 0; }
这种直接越界访问数组的操作,也会造成缓冲区溢出,破坏内存中的其他数据。
最后再划个重点
fgets(buf, n, fp)的核心是最多读n-1个字符,不是只取每行前n-1个,超长行会被分段读取;- 用
fgets+fputs复制文件时,无论缓冲区多大,都能完整复制内容; - 要触发缓冲区溢出,得用不安全的字符串操作或者手动越界,
fgets本身不会导致溢出。
内容的提问来源于stack exchange,提问作者Eric Rawls
相关产品推荐
相关产品推荐

