MAC OS上 结果: 0 32 48
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),作为速度优化,编译器会把变量按机器字对齐,也没有这种效果,总之,缓冲区溢出这
-
种东西很麻烦,搞不清结果会是什么。
-
*/
如上图, 三个变量分配的起始地址分别为0x7fff5fbffb
3c, 0x7fff5fbffb
3b, 0x7fff5fbffb
34
-
/* 地址末两位 */
-
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的并没有截图。
阅读(1413) | 评论(1) | 转发(0) |