为何C语言中用strcpy给小数组赋值却输出完整字符串?
关于C语言strcpy缓冲区溢出导致输出异常的问题
#include <stdio.h> #include <string.h> int main(void) { char s1[6] = "Hello"; char s2[3]; strcpy(s2, s1); printf("%s\n", s2); return 0; }
我编写了上述C语言代码,原本预期输出要么是错误,要么s2的值为{'H', 'e', '\0'},但实际输出却和s1一样是Hello。明明s2仅能容纳3个字符,长度小于s1,请问这是为什么?
strcpy的无边界复制特性:
strcpy函数的工作逻辑是从源字符串起始位置逐个复制字符,直到遇到'\0'终止符才停止,它完全不会检查目标缓冲区的剩余空间。你的s1包含'H'、'e'、'l'、'l'、'o'、'\0'共6个字符,调用strcpy(s2, s1)时,这6个字符会被全部写入s2指向的内存区域——但s2仅分配了3字节的存储空间,这直接触发了缓冲区溢出。内存布局的巧合:在你的程序运行环境中,
s1很可能被编译器分配在s2相邻的内存位置(栈上的变量布局通常由编译器按声明顺序排列)。溢出的字符直接覆盖了s2之后的内存区域,导致从s2起始地址开始的连续内存里,完整存储了"Hello\0"这串数据。printf的输出规则:
printf("%s")是从指定的起始地址开始输出字符,直到遇到'\0'才停止。虽然s2本身只分配了3字节,但溢出后其起始地址往后的内存已经有完整的字符串和终止符,所以printf会输出全部字符,看起来就像s2存储了整个Hello。本质是未定义行为:这种情况属于C语言的未定义行为——C标准没有规定缓冲区溢出后程序的运行结果,不同编译器、不同操作系统甚至不同运行次数下,结果都可能不同:可能输出乱码、程序崩溃,也可能像你这次一样看似“正常”。这种行为完全不可靠,随时可能引发严重问题。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

