VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 2020|回复: 20

[原创] 关于C/C++: 在函数外存取局部变量问题

[复制链接]
79_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-21 09:24:16 | 显示全部楼层 |阅读模式
今天上网看到一个很好玩的也很有深度的C++问题,代码是这样的:

      
#include <iostream>

int * fun()
{
    int a =5;
    return (&a);   //!> 注意一般我们不会这样做的,这是没有意义而且是危险的
}                          //!> 如果想不通,来看看下面吧

int main()
{
    int * p =fun();
    std::cout<< *p;
    *p =8;
    std::cout<< *p;
   return  0;
}

在编译的时候有一个warning:
test.cpp: In function ‘int* fun()’:
test.cpp:7: warning: address of local variable ‘a’ returned

大家可以很快的回答出来答案是5 8对吧~但是你的理解对了吗?看下面~
最终的结果在VC++下,在g++下运行都是C. 58:-)~,下面我们来看看C++内部的实质~
附加:我在GDB调试下的结果:
(gdb) file test
Reading symbols from /home/pt/桌面/test/test...done.
(gdb) r
Starting program: /home/pt/桌面/test/test
58
Program exited normally.

如果你认为是你还是应用了a这个变量,那么你就是大错特错了。熟悉C++的都知道,只要是函数退出了那么局部变量肯定在函数返回之前就释放了,这是必需的,但是我们知道,那个之前保存a的那一块内存还是可以访问的,但是我们访问的时候理论上来说是非法的,因为这就是相当于野指针是吧,呵呵呵~
这个问题的解答是比较简单的,但是这个问题有一个答案中的比喻非常精彩。这个比喻是这样的——
你在某个酒店订了一个房,你入住的时候,你放了一本书在这个酒店的抽屉里,但是你走的时候,你忘了这本书。而且,你还没有把这个房间的钥匙还回去。于是,你在未来某个时候,偷偷地回来,打开这个房间的门,你看到了你的书还在里间。当然,还还可以放回别的书。因为,这个酒店管理不会在你走的时候把你留下的书清走,而且,这个酒店的管理的安保措施不是那么严格,因为他信任每一个客人都会遵守管理条例。在这种情况下,如果你幸运的话,书还会在那里,也可能你的书已经没了。也有可能当你回去的时候,有一个人在那里正在撕你的书,或者酒店把那个抽屉都挪走并变成衣柜,或是整个酒店正在被拆除以改成了一个足球场,而你偷偷摸摸进到施工现场的时候被炸死。
真是很精彩的比喻。这就是C/C++的不安全的地方,也正是Linus说的,C++是一门恐怖的语言是因为有很多不合格的程序员在使用它。就像你看到小孩子玩火一样的恐怖。

我们可以知道:一本书就是a,抽屉就是存放a的内存,钥匙就是说返回a的内存的指针。。。

关于这个事,还有一个比较经典的示例如下——函数a的初始化会影响函数b的数组。注意函数a中的 volatile

关键字。

  1. #include<iostream>
  2. using namespace std;
  3. void a()
  4. {
  5.     volatileint array[10];
  6.     for(int i = 0; i< 10; i++)
  7.    {
  8.         array[i]= i;
  9.    }
  10. }

  11. void b()
  12. {
  13.     intarray[10];
  14.     for(int i = 0; i< 10; i++)
  15.    {
  16.        cout <<array[i];
  17.    }
  18. }

  19. int main()
  20. {
  21.     a();
  22.     b();
  23. }
复制代码


结果是:0123456789,你猜到了吗?:-)~
看一下GDB单步调试:
  1. (gdb) b a
  2. Breakpoint 1 at 0x400788: file t2.cpp, line 6.
  3. (gdb) b b
  4. Breakpoint 2 at 0x4007b6: file t2.cpp, line 15.
  5. (gdb) r
  6. Starting program: /home/pt/桌面/test/t

  7. Breakpoint 1, a () at t2.cpp:6
  8. 6       for (int i =0; i < 10; i++)
  9. (gdb) s
  10. 8          array[i] = i;
  11. (gdb) s
  12. 6       for (int i =0; i < 10; i++)
  13. (gdb) p array[i]
  14. $1 = 0
  15. (gdb) s
  16. 8          array[i] = i;
  17. (gdb) p array[i]
  18. $2 = 32767
  19. (gdb) s
  20. 6       for (int i =0; i < 10; i++)
  21. (gdb) p array[i]
  22. $3 = 1
  23. (gdb) d 1
  24. (gdb) c
  25. Continuing.

  26. Breakpoint 2, b () at t2.cpp:15
  27. 15       for (int i =0; i < 10; i++)
  28. (gdb) p array[i]
  29. $4 =4196000                    //!> 这是b中初始化时候的array时候的随机值,是OK的
  30. (gdb) s
  31. 17          cout << array[i];
  32. (gdb) s
  33. 15       for (int i =0; i < 10; i++)
  34. (gdb) p array[i]
  35. $5 =0                          //!> 看到这一步真的奇怪,为什么就是a中的正常的数呢???
  36. (gdb) s
  37. 17          cout << array[i];
  38. (gdb) p array[i]
  39. $6 =1                          //!> 还有这个,下面就不贴了
复制代码


这是为什么呢?看看volatile关键字吧,

可能很多人都没有用过这个关键字,这个意思就是说:volatile告诉编译器数组是随时可能发生变化的,每次使用它的时候必须从最初的数组array的地址中读取,因而编译器生成的可执行码会重新从原始的数组array的地址读取数据。

评分

参与人数 4驿站币 +5 热心值 +5 收起 理由
93_avatar_small 驿站第一 + 1 + 1 感谢分享!
10_avatar_small cmx006 + 1 + 1 感谢分享!
88_avatar_small 寂寞江湖 + 2 + 2 很给力!
11_avatar_small 饮水机 + 1 + 1 正是我需要的

查看全部评分





上一篇:openwrt挂网web环境的搭建系统环境
下一篇:c语言代码如何优化
94_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-21 10:09:04 | 显示全部楼层
想看学习啊
06_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-21 10:22:48 | 显示全部楼层
看看是神马东西
74_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-21 11:13:35 | 显示全部楼层
look     
24_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-21 14:42:32 | 显示全部楼层
学习   
94_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-21 16:02:58 | 显示全部楼层
学习依稀啊
56_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-21 18:29:29 | 显示全部楼层
学习一下!
08_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-22 08:32:03 | 显示全部楼层
关于C/C++: 在函数外存取局部变量问题
49_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-22 11:39:45 | 显示全部楼层
看看 是什么啊
17_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-22 15:39:37 | 显示全部楼层
什么东东
02_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-22 18:43:13 | 显示全部楼层
看看         
00_avatar_middle
最佳答案
0 
online_vip 发表于 2016-4-23 14:58:56 | 显示全部楼层
看看是个什么
10_avatar_middle
最佳答案
3 
在线会员 发表于 2016-4-23 17:41:55 | 显示全部楼层
在函数外还没访问局部变量吗?除了静态变量
11_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-28 22:02:14 | 显示全部楼层
学习了  收藏
88_avatar_middle
最佳答案
0 
online_vip 发表于 2016-4-29 13:17:19 | 显示全部楼层
谢谢分享 啊
83_avatar_middle
最佳答案
0 
在线会员 发表于 2016-4-29 20:21:46 | 显示全部楼层
这个会不会把程序的结构弄混了。
51_avatar_middle
最佳答案
0 
在线会员 发表于 2016-5-6 20:01:06 | 显示全部楼层
谢谢分享
35_avatar_middle
最佳答案
0 
在线会员 发表于 2016-5-7 16:47:43 | 显示全部楼层
为什么要这么做啊?
79_avatar_middle
最佳答案
0 
ico_lz  楼主| 发表于 2016-5-8 08:09:27 | 显示全部楼层
人走茶不凉 发表于 2016-5-7 16:47
为什么要这么做啊?

请给我加热心之啊
40_avatar_middle
最佳答案
0 
在线会员 发表于 2016-5-13 08:58:54 | 显示全部楼层
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

×【发帖 友情提示】
1、请回复有意义的内容,请勿恶意灌水;
2、纯数字、字母、表情等无意义的内容系统将自动删除;
3、若正常回复后帖子被自动删除,为系统误删的情况,请重新回复其他正常内容或等待管理员审核通过后会自动发布;
4、感谢您对VC驿站一如既往的支持,谢谢合作!

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号 )|网站地图wx_jqr

GMT+8, 2020-10-29 01:58

Powered by CcTry.CoM

© 2009-2020 cctry.com

快速回复 返回顶部 返回列表