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

C语言使用gets函数操作字符串溢出无警告问题求解

C语言gets函数缓冲区溢出问题解决方案

gets 函数从设计层面就没有提供缓冲区长度校验机制,它会持续读取标准输入内容直到遇到换行符或EOF,完全不考虑目标字符数组的容量上限,只要输入长度超过数组大小就会触发缓冲区溢出,属于典型的未定义行为。正因为这个严重的安全缺陷,gets 函数已经在C11标准中被正式移除,不建议在任何生产代码中使用。

你遇到的「输入超出数组容量仍能正常打印」只是未定义行为的一种表现,本质是越界写入了数组后方的内存空间,这种情况随时可能导致程序崩溃、数据篡改甚至被注入恶意代码。gets 本身的逻辑无法在编译期判断输入长度,运行时也没有边界检查逻辑,因此不可能依赖编译器主动抛出这类溢出警告。


具体解决方案

  • 首选方案:使用fgets函数替换gets
    fgets 函数需要显式传入缓冲区大小参数,只会读取最多「缓冲区长度-1」个字符,最后自动补字符串结束符\0,从根本上避免缓冲区溢出。它的调用格式为:
    fgets(目标缓冲区指针, 缓冲区大小, 输入流);
    
    注意fgets会将输入末尾的换行符\n也存入缓冲区,如果不需要可以手动清除:
    // 清除fgets读取到的末尾换行符
    char *p = strchr(name, '\n');
    if (p) *p = '\0';
    
    修改后的完整代码示例:
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        // 根据实际需要设置足够的缓冲区大小即可
        char name[100];
    
        printf("Enter the name : ");
        fgets(name, sizeof(name), stdin);
        // 清除末尾换行符
        char *p = strchr(name, '\n');
        if (p) *p = '\0';
        printf("Print the name through the user : ");
        puts(name);
    
        return 0;
    }
    
  • 开启编译器的安全编译选项
    日常开发时建议开启最高警告等级和栈保护机制,例如使用GCC编译时加上以下参数:
    gcc test.c -o test -Wall -Wextra -fstack-protector-all
    
    开启后编译器会对可能的溢出风险给出警告,运行时如果发生栈溢出会直接终止程序,降低安全风险。
  • 兼容C11的场景下可使用gets_s
    C11标准新增了安全版本的gets_s函数,同样需要传入缓冲区大小参数,但该函数属于标准可选实现,兼容性不如fgets,跨平台开发不优先推荐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 15:30:02