sprintf()函数为何修改输入参数?数组越界引发变量异常
为什么sprintf()会意外修改输入变量?
我们先看两段测试代码的运行现象:
第一段代码(符合预期)
#include <iostream> int main(int argc, char *argv[]) { int i = 10; char c[3]; std::cout << i << std::endl; sprintf(c, "%d", i); std::cout << i << std::endl; return 0; }
执行结果:10 10,和预期一致,变量i的值没有被改变。
第二段代码(出现异常)
#include <iostream> int main(int argc, char *argv[]) { int i = 100; char c[3]; std::cout << i << std::endl; sprintf(c, "%d", i); std::cout << i << std::endl; return 0; }
执行结果:100 0,变量i的值被意外修改了。
问题原因分析
核心问题是缓冲区溢出(Buffer Overflow):
- 你定义的
char c[3]只分配了3个字节的内存空间。 - 当
i=100时,sprintf()会把数字转换成字符串"100",再加上C字符串必须的终止符'\0',一共需要4个字节的空间才能容纳。 - 由于
sprintf()本身不会检查目标缓冲区的大小,它会直接往c里写入这4个字节,超出缓冲区的部分就会覆盖栈上相邻内存区域的数据。 - 在你的程序栈布局中,变量
i正好位于c的相邻位置(栈的生长方向通常是从高地址到低地址,所以数组c的末尾之后就是i的内存),溢出的字节直接改写了i的值,导致输出变成了0。
而第一段代码中i=10,转换成字符串是"10"加上终止符'\0'一共3个字节,刚好填满c的缓冲区,没有溢出,所以i的值不受影响。
内容的提问来源于stack exchange,提问作者Alexander Zolkin
相关产品推荐
相关产品推荐

