C语言字符串缓冲区溢出为何引发异常行为?
缓冲区溢出导致的内存异常解析
核心问题根源
你遇到的所有异常都是**缓冲区溢出+缺失字符串终止符\0**导致的:C语言字符串必须以\0结尾,而你定义的b[5]、c[5]、arr[2][5]每个数组仅能容纳4个有效字符+1个\0,输入5个字符时会填满数组,既没有空间存\0,还会溢出覆盖相邻内存。
为什么arr[0]输出为somewsomew
arr是连续的内存块:arr[0]占前5字节,arr[1]紧接着占后5字节。
当输入5个字符"somew"时:
b被填满,无\0;strcpy(arr[0], b)把5个字符复制到arr[0],同样arr[0]无\0;- 第二个"somew"写入
c后复制到arr[1],arr[1]也无\0; printf("%s", arr[0])会从arr[0]起始地址一直读字符,直到遇到\0才停止。因为arr[0]没有终止符,它会继续读取后面的arr[1]内容,于是把两个"somew"连在一起输出成somewsomew。而arr[1]后面的内存恰好存在\0(栈上的默认空值或其他变量的终止符),所以arr[1]的输出看起来正常。
为什么最后变量b为空
栈上变量的布局(取决于编译器)中,c的内存紧邻b的起始地址:
当用scanf("%s", c)输入5个字符时,scanf会自动在字符串末尾添加\0,但c的5字节已被填满,这个\0就会溢出到c后面的内存——也就是b的第一个字节位置。b的首字节被改成\0后,所有字符串操作(printf、strcmp)都会把它识别为空字符串,所以最后输出中b显示为空。
修复方案
- 限制输入长度:使用
scanf("%4s", b),强制只读取4个字符,预留1字节给\0; - 扩容数组:把
b[5]、c[5]、arr[2][5]改成至少[6],容纳5个字符+1个终止符; - 安全复制字符串:用
strncpy代替strcpy,并手动添加终止符,比如:strncpy(arr[0], b, 4); arr[0][4] = '\0';
内容的提问来源于stack exchange,提问作者Emiya
相关产品推荐
相关产品推荐

