Win7 VS2005上:24 32 48
- #include "stdafx.h"
- #include <stdio.h>
- int main(int argc,char* argv)
- {
- int var1=0;
- char var2=0;
- int var3=0;
- char str_val1[]="24\n";
- char str_val2[]="32\n";
- char str_val3[]="48\n";
- sscanf(str_val1,"%d",&var1);
- sscanf(str_val2,"%d",&var2);
- sscanf(str_val3,"%d",&var3);
- printf("var1=%d,var2=%d,var3=%d\n",var1,var2,var3);
- return 0;
- }
- /*
- 不同的编译器可能有不同的结果,加上优化选项也可能有不同的结果,之所以有这样的结果是因为
- 缓冲区溢出, sscanf(str_val2,"%d",&var2)中的var2是char,只占一个字节,当作为%d格式
- 的时候实际写了4个字节,声明的时候var1在var2前面,所以就把var1覆盖了3个字节,这和机器
- 堆栈的生长方向也有关,如果栈是向上生长的就没有这种效果,还和str_var的值有关,var1太大
- 就不会被覆盖完(不等于0),var2太大就会影响var1(值不一定),如果编译的时候加了优化选项
- (gcc -O),作为速度优化,编译器会把变量按机器字对齐,也没有这种效果,总之,缓冲区溢出这
- 种东西很麻烦,搞不清结果会是什么。
- */
如上图, 三个变量分配的起始地址分别为0x7fff5fbffb3c, 0x7fff5fbffb3b, 0x7fff5fbffb34
- /* 地址末两位 */
- 3C 3D 3E 3F var1 3C: 起始地址
- 38 39 3A 3B var2 3B: 起始地址
- 34 35 36 37 var3 34: 起始地址
- 第一:不明白为啥 var2不分配在38起始
- 第二:既然分配了在3B起始, 为啥前面的38,39,3A都留空了?
- 因为var3分配到了34
- 这样如果在var2地址,也就是3B处写入%d的数据,那么3B 3C 3D 3E都会被覆盖
- 所以var1也就为0了. VS2005并没有覆盖,可能需要一个较大的数才能覆盖
MAC OS 和Win7 VS2005上地址情况时类似的,如果var2写入四个字节都会覆盖var1,
但是奇怪的是两者输出结果并不一样,VS2005的并没有截图。