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

字符串内存分配疑问:分配10字符空间输入11字符为何结果正常?

关于C语言字符串内存越界的疑问与解答

问题描述

我知道给字符串分配内存时,因为要存储NULL终止符,得分配n+1的空间,但我有个疑问:如果只分配10个字符的内存空间,却输入11个字符的字符串会发生什么?我运行了测试代码,结果居然和分配n+1空间时的表现一致,代码如下:

#include <stdlib.h>
#include <stdio.h>  // 注:原代码遗漏该头文件,printf/scanf需依赖它
int main(){
    int n;
    char *str;
    printf("How long is your string? ");
    scanf("%d", &n);
    str = malloc(n+1);
    if (str == NULL) printf("Uh oh.\n");
    scanf("%s", str);
    printf("Your string is: %s\n", str);
}

解答

首先明确:这种输入长度超过分配内存的行为属于缓冲区溢出,是C语言里的未定义行为,绝非正常程序逻辑。

  • 为什么测试时表现和正常情况一致?
    这纯粹是运气好——你写入的额外字符刚好覆盖了当前内存块后方的“空闲”区域,暂时没破坏程序的关键数据(比如函数返回地址、其他变量的值),所以程序还能正常执行。但这种情况完全随机,换个编译环境、操作系统,甚至同一程序多运行几次,结果可能天差地别:

    • 轻则程序直接崩溃(段错误);
    • 重则破坏其他变量的值,导致程序逻辑混乱,输出错误结果;
    • 极端情况下,恶意输入可利用该漏洞执行任意代码,引发安全风险。
  • 为什么scanf("%s")存在风险?
    这个函数不会检查目标缓冲区的大小,不管你分配了多少空间,它都会持续读取输入直到遇到空白字符,一旦输入长度超过缓冲区,必然引发溢出。正确的做法是限制读取长度,比如用scanf("%10s", str)(这里的10是缓冲区可容纳的最大字符数,不含NULL终止符),或者使用更安全的fgets读取字符串,后续再处理换行符。

  • 补充说明:原代码还有一个问题——未包含<stdio.h>头文件,printf和scanf属于该头文件中的函数,虽然部分编译器能通过编译,但这不符合C标准规范,同样会导致未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 00:32:52