You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何fgets返回的局部缓冲区地址在函数执行后会失效?

问题解析与解答

[编辑:显然fgets的返回值就是所使用的char buffer[SIZE]的地址,因此在我的案例中这是合理的,因为我将其声明为局部变量(即块作用域)。附:感谢所有帮助!]

为什么函数执行完后fgets存储的数据会意外改变?

核心原因是**ptr_one指向的是栈上的局部变量buffer**。input_string函数里的buffer是块作用域的局部数组,分配在栈帧上。当函数执行完毕返回时,这个栈帧会被销毁,buffer占用的内存空间会被系统回收,后续的函数调用(比如main里的printf)会复用这块栈内存,导致原来存储的内容被覆盖,所以你看到ptr_one指向的内容意外改变。

fgets返回的数据有生命周期吗?

fgets本身不负责管理内存,它只是把读取到的内容写入你传入的目标缓冲区。数据的生命周期完全由你传入的缓冲区的生命周期决定:

  • 如果缓冲区是栈上的局部变量,生命周期仅限于当前函数/代码块;
  • 如果是堆上分配的内存(比如malloc出来的),生命周期直到你调用free释放它;
  • 如果是全局/静态变量,生命周期和程序一致。

fgets这类函数是如何实现的?它能追踪用户的调用作用域吗?

fgets不需要追踪调用作用域,它的核心逻辑很直白:

  1. 接收你传入的缓冲区地址、最大读取长度、输入流;
  2. 从输入流中逐个读取字符,写入缓冲区;
  3. 直到遇到换行符、读取到指定长度-1的字符(留一个位置存终止符'\0'),或者输入流到达末尾/出错;
  4. 最后在缓冲区末尾添加'\0',成功时返回你传入的缓冲区地址,失败/到达文件尾时返回NULL。

它的实现根本不关心你传入的缓冲区属于什么作用域,只负责往指定地址写数据——内存的生命周期管理完全是调用者的责任。

你的示例代码问题点

  • *pptr_one = x;:x是局部数组buffer的地址,函数退出后这个地址变成野指针,访问它属于C语言中的「未定义行为」,结果不可预测;
  • *pptr_two = malloc(SIZE); strcpy(*pptr_two, x);:这部分是正确的,因为malloc分配的是堆内存,生命周期不受函数作用域限制,所以ptr_two指向的内容能正常保留。

内容的提问来源于stack exchange,提问作者Sai Surisetti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 20:27:48