问题:Can a local variable’s memory be accessed outside its scope? 有一段局部变量的内存,可以从其范围之外访问它么?如下代码:
这样的代码可以正常执行,而且没有任何运行时的异常! 输出是 这是怎么回事?难道局部变量在函数外也可以被访问吗?
来自微软资深软件工程师 Eric Lippert 的最佳答案(3200+赞):你在酒店里租了一间房。你把一本书放进了桌子的第一个抽屉里,然后就去睡觉了。当你第二天早上醒来时,你假装忘记去还钥匙了。你偷了房间的钥匙! 一周之后,你回到了酒店,但没有入住,你用偷来的钥匙溜进了你上次入住的房间,并查看了那个抽屉。你的书还在那里。是不是很令人吃惊! 这是怎么回事呢?难道一个酒店房间的抽屉不是应该无法被一个没有入住这个房间的人看到吗? 好吧,明显的是,这种情况在真实世界中当然会发生。在你不入住这个房间的时候,这里面没有任何神秘的力量把你的书弄消失掉,也没有魔法能够阻止你用偷来的钥匙进入房间。 酒店的管理规章里没有要求拿走你的书。你也没有跟他们说如果你落下了一本书,他们可以帮你撕毁它。如果你用偷来的钥匙非法进入了你上次的房间,并且没有被酒 店的安保系统发现。你也没有跟他们说如果你之后尝试溜进房间,他们应该阻止你。不过事实上,你确实签了一份协议规定你保证不会偷偷溜回房间。只不过你打破 了协议。 在这种情况下任何事情都有可能发生。如果你运气好的话,那本书可能还在那里。其他人的书也可能在那个抽屉里而你的书则被丢进了酒店的火炉里。也可能当你溜进 去的时候正好有个人在把你的书撕成碎片。酒店可能把那张桌子连带你的书都移走了,而把一个衣柜放在那里。这家酒店也可能正好要被拆除,换成一个足球场,在 你溜来溜去的时候。你可能会在一场爆破中死去。 当你离开酒店而偷了房间的钥匙的时候,你不知道将会发生什么。你放弃了去生活在一个可靠的,安全的世界里,因为你选择去打破系统的规则。 C++ 不是一门安全的语言。你可以非常轻松就打破这个系统的规则。如果你尝试去做一些非法并且愚蠢的事情,比如你回到那个你已经不入住的房间,并想要去查看那张 也许已经不存在的桌子。C++不会阻止你的。比C++更加安全的语言通过限制你的能力来解决这个问题,比如通过更加严格的控制房间钥匙。 【更新】: 我的老天。这个答案获得了这么多的关注。(我不知道为什么,我只是觉得这样比喻比较有趣, 不过管他呢。) 我认为在经过了更加技术性的思考之后更新一下这个答案是必要的。 编译器的工作是生成代码来管理这个程序数据拥有的内存。有很多方式来生成管理内存的代码,但是这么多年来有两个基本的技术是必须要知道的。 第一个是拥有一片长期存在的区域,这片存储区域里的每一个字节,他们的生命周期比较长。生命周期的意思就是它们能够被程序访问的时期。这类内存没办法提前进 行预估。编译器生成一种叫堆管理器的代码,它知道如何在需要的时候动态的分配内存,当内存不再被需要的时候释放掉他们。 第二个是拥有一片短期存在的区域,这片存储区域里的每一个字节都可以提前进行预估。而且比较特殊的是,这片区域的生命周期遵循一种嵌套模式。也就是说,在这片区域中拥有最长生命周期的变量,它所分配的内存地址被它之后分配的那些生命周期较短的变量所重用。 局部变量就是第二种情况。当调用一个函数时,它的局部变量便被生成了。当这个函数调用另外一个函数时,新函数的局部变量也被生成了。这些变量会在第一个函数的局部变量之前被释放掉。这些局部变量的内存地址的开始和结束可以提前被计算出来。 |