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

C语言使用strncpy()触发缓冲区溢出的内存行为疑问

strncpy缓冲区溢出现象答疑

复现代码

#include<stdio.h>
#include<string.h>
int main(){
    char arr1[]="Buffer overflow";
    char arr2[5];
    printf("Size of array1 %d\n",sizeof(arr1));
    strncpy(arr2,arr1,20);
    printf("\nAfter copy\n");
    printf("Length of arr2: %d\n",strlen(arr2));
    printf("Size of arr2: %d\n",sizeof(arr2));
    printf("Arr2: %s\n",arr2);
    return 0;
}

运行输出

Size of array1 16

After copy
Length of arr2: 15
Size of arr2: 5
Arr2: Buffer overflow

核心原因拆解

不存在“5字节数组自动变长容纳内容”的情况,你观察到的矛盾现象本质是混淆了C语言的不同机制,同时触发了未定义的缓冲区溢出行为,具体逻辑如下:

1. 两个长度相关操作的本质完全不同

  • sizeof是编译期运算符,不是运行时函数。arr2声明为char[5]类型,它的大小在编译阶段就已经固定,代码里的sizeof(arr2)会被编译器直接替换为常量5,和运行时往对应内存写了什么内容毫无关系,所以输出永远是5。
  • strlen是运行时库函数,它完全不知道传入的数组原本声明了多大,唯一的工作逻辑是:从传入的内存地址开始逐字节遍历,直到遇到第一个值为'\0'的字符串终止符就停止,返回遍历过的非0字节总数。

2. 你看到的“装下20字节”本质是缓冲区溢出

C语言本身不会在运行时做数组边界检查,你声明arr2[5]只是向编译器申请了5字节的合法访问空间,不代表写入超过5字节就会立刻被系统拦截。
程序运行时arr2被分配在栈内存上,它后面紧邻着其他可读写的栈空间(可能是其他临时变量、栈对齐填充位、保存的寄存器值等)。调用strncpy(arr2, arr1, 20)时,strncpy不会检查目标缓冲区的实际大小,只会从arr2的起始地址开始忠实地写入20字节:

  • 前15字节写入arr1存储的Buffer overflow字符
  • 第16字节写入arr1末尾自带的'\0'终止符
  • 剩余4字节按照strncpy的规则补填'\0'
    从第6字节开始,写入的内容就已经超出了arr2的合法范围,覆盖了arr2后面的栈内存,这就是典型的栈缓冲区溢出,属于C标准明确规定的未定义行为。
    后续调用strlen和printf输出字符串时,都是从arr2的起始地址开始遍历,直到第16位碰到写入的'\0'才停止,自然会得到15的长度值、输出完整的字符串。

注意事项

这次运行没有崩溃完全是概率事件:刚好越界写入的栈区域是可写的,没有覆盖栈保护校验值、函数返回地址等关键数据,也没有触发内存访问权限异常。这类越界代码没有任何可移植性,换编译选项(比如开启栈保护)、调整变量声明顺序、换编译器版本,都可能直接导致程序崩溃、输出乱码,甚至留下可被利用的安全漏洞。
另外需要注意:strncpy不是设计用来做安全字符串拷贝的函数,它不会自动校验目标缓冲区容量,当传入的拷贝长度超过缓冲区大小时,必然产生越界写入,本身就是C语言缓冲区溢出的高发诱因。


内容的提问来源于stack exchange,提问作者hari hara sankar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 16:03:30