为何fgets返回的局部缓冲区地址在函数执行后会失效?
问题解析与解答
[编辑:显然fgets的返回值就是所使用的char buffer[SIZE]的地址,因此在我的案例中这是合理的,因为我将其声明为局部变量(即块作用域)。附:感谢所有帮助!]
为什么函数执行完后fgets存储的数据会意外改变?
核心原因是**ptr_one指向的是栈上的局部变量buffer**。input_string函数里的buffer是块作用域的局部数组,分配在栈帧上。当函数执行完毕返回时,这个栈帧会被销毁,buffer占用的内存空间会被系统回收,后续的函数调用(比如main里的printf)会复用这块栈内存,导致原来存储的内容被覆盖,所以你看到ptr_one指向的内容意外改变。
fgets返回的数据有生命周期吗?
fgets本身不负责管理内存,它只是把读取到的内容写入你传入的目标缓冲区。数据的生命周期完全由你传入的缓冲区的生命周期决定:
- 如果缓冲区是栈上的局部变量,生命周期仅限于当前函数/代码块;
- 如果是堆上分配的内存(比如
malloc出来的),生命周期直到你调用free释放它; - 如果是全局/静态变量,生命周期和程序一致。
fgets这类函数是如何实现的?它能追踪用户的调用作用域吗?
fgets不需要追踪调用作用域,它的核心逻辑很直白:
- 接收你传入的缓冲区地址、最大读取长度、输入流;
- 从输入流中逐个读取字符,写入缓冲区;
- 直到遇到换行符、读取到指定长度-1的字符(留一个位置存终止符
'\0'),或者输入流到达末尾/出错; - 最后在缓冲区末尾添加
'\0',成功时返回你传入的缓冲区地址,失败/到达文件尾时返回NULL。
它的实现根本不关心你传入的缓冲区属于什么作用域,只负责往指定地址写数据——内存的生命周期管理完全是调用者的责任。
你的示例代码问题点
*pptr_one = x;:x是局部数组buffer的地址,函数退出后这个地址变成野指针,访问它属于C语言中的「未定义行为」,结果不可预测;*pptr_two = malloc(SIZE); strcpy(*pptr_two, x);:这部分是正确的,因为malloc分配的是堆内存,生命周期不受函数作用域限制,所以ptr_two指向的内容能正常保留。
内容的提问来源于stack exchange,提问作者Sai Surisetti
相关产品推荐
相关产品推荐

