Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1562567
  • 博文数量: 327
  • 博客积分: 10000
  • 博客等级: 上将
  • 技术积分: 3556
  • 用 户 组: 普通用户
  • 注册时间: 2005-04-05 21:28
个人简介

东黑布衣,流浪幽燕。 真诚善良,值得信赖。

文章分类

全部博文(327)

我的朋友

分类: BSD

2018-04-30 22:56:55

MAC OS上 结果: 0 32 48
Win7 VS2005上:24 32 48

  1. #include "stdafx.h"
  2. #include <stdio.h>

  3. int main(int argc,char* argv)
  4. {
  5.    int var1=0;
  6.    char var2=0;
  7.    int var3=0;
  8.    char str_val1[]="24\n";
  9.    char str_val2[]="32\n";
  10.    char str_val3[]="48\n";
  11.    sscanf(str_val1,"%d",&var1);
  12.    sscanf(str_val2,"%d",&var2);
  13.    sscanf(str_val3,"%d",&var3);
  14.    printf("var1=%d,var2=%d,var3=%d\n",var1,var2,var3);
  15.    return 0;
  16. }
  17. /*
  18. 不同的编译器可能有不同的结果,加上优化选项也可能有不同的结果,之所以有这样的结果是因为
  19. 缓冲区溢出, sscanf(str_val2,"%d",&var2)中的var2是char,只占一个字节,当作为%d格式
  20. 的时候实际写了4个字节,声明的时候var1在var2前面,所以就把var1覆盖了3个字节,这和机器
  21. 堆栈的生长方向也有关,如果栈是向上生长的就没有这种效果,还和str_var的值有关,var1太大
  22. 就不会被覆盖完(不等于0),var2太大就会影响var1(值不一定),如果编译的时候加了优化选项
  23. (gcc -O),作为速度优化,编译器会把变量按机器字对齐,也没有这种效果,总之,缓冲区溢出这
  24. 种东西很麻烦,搞不清结果会是什么。
  25. */


如上图, 三个变量分配的起始地址分别为0x7fff5fbffb3c, 0x7fff5fbffb3b, 0x7fff5fbffb34


  1. /* 地址末两位 */
  2. 3C 3D 3E 3F var1 3C: 起始地址
  3. 38 39 3A 3B var2 3B: 起始地址
  4. 34 35 36 37 var3 34: 起始地址
  5. 第一:不明白为啥 var2不分配在38起始
  6. 第二:既然分配了在3B起始, 为啥前面的38,39,3A都留空了?
  7. 因为var3分配到了34

  8. 这样如果在var2地址,也就是3B处写入%d的数据,那么3B 3C 3D 3E都会被覆盖
  9. 所以var1也就为0了. VS2005并没有覆盖,可能需要一个较大的数才能覆盖



MAC OS 和Win7 VS2005上地址情况时类似的,如果var2写入四个字节都会覆盖var1,
但是奇怪的是两者输出结果并不一样,VS2005的并没有截图。






阅读(1413) | 评论(1) | 转发(0) |
0

上一篇:C语言杂记

下一篇:20180501

给主人留下些什么吧!~~

zhln2018-05-04 21:11:55

哪些方式优化代码:
1.内联函数或者宏函数
2.指针代替数组
3.不定义不使用的返回值
4.使用寄存器变量
5.内嵌汇编
6.使用增量操作符
7.减少函数的参数
8.switch发生频繁的放在前面
9.尽量避免打断CPU流水
A.bit运算代替Mod操作
B.迭代代替递归