- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有以下代码。
#include <iostream>
int * foo()
{
int a = 5;
return &a;
}
int main()
{
int* p = foo();
std::cout << *p;
*p = 8;
std::cout << *p;
}
58
最佳答案
怎么可能?局部变量的存储不是在函数之外不可访问的吗?
您租了旅馆房间。您将一本书放在床头柜的顶部抽屉中,然后入睡。您第二天早上退房,但是“忘记了”退还您的钥匙。您偷了钥匙!
一周后,您返回酒店,不办理入住手续,用偷来的钥匙偷偷进入旧房间,然后看向抽屉。你的书还在那里。惊人!
这个怎么可能?如果您没有租房,不是不是无法进入酒店房间抽屉的内容吗?
好吧,很明显,这种情况可以在现实世界中发生,没有问题。当您不再被授权进入房间时,没有任何神秘的力量会使您的书消失。也没有一种神秘的力量阻止您使用失窃的钥匙进入房间。
不需要酒店管理人员删除您的书。您没有与他们签订合同,说如果您留下东西,他们会为您切碎。如果您用偷来的钥匙非法重新进入房间以将其取回,则无需酒店安全人员抓住您潜行。您没有与他们订立合同,说“如果我尝试潜入我的房间,房间之后,您必须阻止我。”相反,您与他们签订了一份合同,上面写着“我保证以后不会再潜入我的房间”,这是您违反的合同。
在这种情况下,任何事情都可能发生。这本书可以在那里-您很幸运。可能有人的书在那里,而您的书可能在酒店的炉子里。当您进来时,有人可能会在那里,将您的书撕成碎片。该酒店本可以删除桌子并完全预订,然后用衣柜代替。整个酒店可能会被拆毁,取而代之的是一个足球场,而当您潜行时,您将在爆炸中丧生。
您不知道会发生什么;当您退出酒店并偷走了以后非法使用的钥匙时,您放弃了生活在可预测的安全世界中的权利,因为您选择了违反系统规则。
C ++不是安全的语言。它会很乐意让您打破系统规则。如果您尝试做一些非法和愚蠢的事情,例如回到没有权限的房间,或者翻阅一张可能根本不在的桌子,那么C ++不会阻止您。比C ++更安全的语言通过限制您的力量来解决此问题-例如,通过对键进行更严格的控制。
更新
天哪,这个答案引起了很多关注。 (我不确定为什么-我认为这只是一个“有趣”的小类比,但无论如何。)
我认为用一些其他技术思想来对此进行更新可能是很紧要的。
编译器负责生成代码,该代码管理该程序处理的数据的存储。生成代码来管理内存的方法有很多,但是随着时间的流逝,两种基本技术已经根深蒂固。
第一种是具有某种“长寿”的存储区域,在该区域中,存储中每个字节的“生存期”(即与某个程序变量有效关联的时间段)无法轻易地预先预测时间。编译器生成对“堆管理器”的调用,该堆管理器知道如何在需要时动态分配存储,并在不再需要时回收它。
第二种方法是拥有一个“短暂的”存储区域,其中每个字节的生存期众所周知。在此,生命周期遵循“嵌套”模式。这些短期变量中寿命最长的变量将在任何其他短期变量之前分配,最后释放。寿命较短的变量将在寿命最长的变量之后分配,并在它们之前被释放。这些寿命较短的变量的寿命被“嵌套”在寿命较长的变量的寿命之内。
局部变量遵循后一种模式;输入方法后,其局部变量将生效。当该方法调用另一个方法时,新方法的局部变量将生效。在第一个方法的局部变量失效之前,它们将失效。可以提前确定与局部变量关联的存储生命周期的开始和结束的相对顺序。
由于这个原因,局部变量通常作为“堆栈”数据结构上的存储生成,因为堆栈具有的属性是,首先要压入的堆栈将是最后弹出的堆栈。
就像酒店决定只按顺序出租房间一样,只有在房间号高于您所选择的每个人之前,您都无法退房。
因此,让我们考虑一下堆栈。在许多操作系统中,每个线程获得一个堆栈,并且该堆栈被分配为一定的固定大小。调用方法时,东西被压入堆栈。如果您随后将指针传递回方法之外的堆栈,就像原始海报在此处所做的那样,那仅是指向某些完全有效的百万字节内存块中间的指针。打个比方,您从酒店退房;当您这样做时,您只是从编号最高的占用房间中退出。如果在您之后没有其他人入住,并且您非法返回房间,则可以保证所有物品仍在此特定酒店中。
我们将堆栈用于临时存储,因为它们确实便宜又容易。不需要使用C ++实现就可以使用堆栈来存储本地对象;它可以使用堆。事实并非如此,因为那会使程序变慢。
不需要C ++的实现就可以使您留在堆栈上的垃圾保持不变,以便以后可以非法返回它。编译器生成将刚腾出的“房间”中的所有内容都归零的代码是完全合法的。并不是因为这又会很昂贵。
不需要C ++的实现来确保在逻辑上缩小堆栈时,曾经有效的地址仍会映射到内存中。该实现被允许告诉操作系统“我们现在已经完成了该堆栈页面的使用。除非我另有说明,否则,如果有人触摸了先前有效的堆栈页面,则发出一个异常,该异常会破坏进程”。再次,实现实际上并没有这样做,因为它很慢且不必要。
取而代之的是,实现使您能够犯错误并摆脱错误。大多数时候。直到有一天,真正可怕的事情出了问题,整个过程爆炸了。
这是有问题的。有很多规则,很容易意外地打破它们。我当然有很多次。更糟糕的是,问题通常仅在损坏发生后检测到内存损坏数十亿纳秒时才浮出水面,而很难弄清楚是谁弄乱了内存。
更多的内存安全语言通过限制您的能力来解决此问题。在“普通” C#中,根本没有办法获取本地地址并将其返回或存储以供以后使用。您可以使用本地地址,但是语言设计巧妙,因此在本地生命周期结束后无法使用它。为了获取本地地址并将其传递回去,您必须将编译器置于特殊的“不安全”模式,并将“不安全”一词放入程序中,以引起注意以下事实:可能违反规则的危险。
进一步阅读:
如果C#允许返回引用怎么办?巧合的是,这是今天的博客文章的主题:
http://blogs.msdn.com/b/ericlippert/archive/2011/06/23/ref-returns-and-ref-locals.aspx
为什么我们使用堆栈来管理内存? C#中的值类型是否始终存储在堆栈中?虚拟内存如何工作?还有更多有关C#内存管理器如何工作的主题。这些文章中有许多也与C ++程序员紧密相关:
https://blogs.msdn.microsoft.com/ericlippert/tag/memory-management/
关于c++ - 是否可以在其范围之外访问局部变量的内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34817895/
我正在努力解决一个问题 Rahul 正在玩一个非常有趣的游戏。他有 N 个圆盘(每个圆盘的半径相等)。每个磁盘都有一个不同的数字,从 1 到 N 与之相关联。磁盘一个接一个地放在一堆中。 Rahul
我正在尝试使用此代码发出请求: public JsonObject account() throws BinanceApiException { return (new Request
我使用的是 Mac OS 和 emacs -nw (终端模式)。 我不知道如何在 emacs 之外粘贴东西(已由 M-w 在 emacs -nw 中实现)。 我知道emacs -ns可以做到。 搜索互
我试图让导航栏菜单出现在“标题容器”菜单中,但由于某种原因,导航栏链接流到外面(在修改浏览器窗口之前)。我不明白为什么,但我怀疑它与这一行有关: div class="collapse navbar-
我们的项目是在 WAS 6.1/hibernate/struts 上使用 RAD 7.0 开发的中型 Web 应用程序,该应用程序已投入生产。目前我们在属性文件中硬编码了生产系统的 IP 地址,在 h
我的要求是在传单中创建 N 类型的标记。该列表很大,无法容纳在 map 区域中。 我想要类似的东西: http://blog.georepublic.info/2012/leaflet-example
如 docs 中所述,基于 spring-boot 的 Web 服务正在使用 Sentry .它工作正常,但不应将某些异常发送到 Sentry ,例如为了在某些请求上返回 HTTP 状态 410
我已经阅读了 Apple Core Animation 文档。它说核心动画没有提供在窗口中实际显示图层的方法,它们必须由 View 托管。当与 View 配对时, View 必须为底层图层提供事件处理
我试图在滚动时检查元素是否在我的视口(viewport)内。如果它在我的视口(viewport)之外,我会添加一个类来将元素固定到顶部。 我用来确定元素是否在视口(viewport)之外的函数是: i
我正在查询中创建一个弹出窗口。悬停时弹出窗口一切正常。当用户的鼠标离开 div 以关闭它时,我让它看到计时器启动。如果他在计时器完成之前再次进入 div,则计时器将被清除。 这很好,但是如果用户点击
我使用名为 zonemap 的字典创建了一个 4x6 区域 map 。我在该字典中嵌套了多个字典;每个区域代表玩家可以访问并与之互动的区域。我希望能够将玩家的移动限制在该 4x6 区域,并重新显示他们
我正在构建一个页面,该页面将使用 ajax 来更新主要内容区域。用户将单击左侧菜单栏中的项目来更新右侧的 div 并包含搜索结果。 我想检测用户是否向下滚动到目前为止导致右侧结果 div 移出视口(v
好的,我在 div 中有一个带有拖放类的表格,其溢出设置为“自动”,这允许我隐藏部分时间表,只在底部放置一个滚动条。但是,我只是在可滚动 div 之外创建了一些可放置元素,并且我的可拖动元素无法离开可
我有大量项目绑定(bind)到 ListBox,VirtualizingStackPanel 设置为它的 ItemsPanel。随着用户滚动和项目容器的创建,我做了一些工作来用数据填充项目(使用数据库
我想知道是否有一种方法可以将类成员的访问范围专门限定为在 C# 中获取/设置实现,以减少我意外直接访问它们的可能性。类似 private 的东西,但只允许 get/set 访问它,我想我可以将每个变量
我正在尝试编写一个小游戏,以应用我自己在本类(class)中学到的概念。当游戏打开时,我想要一个自定义模态视图来告诉用户如何玩。同样,当他们输了时,我想呈现一个结果页面,该页面将位于 if 语句内。我
我有一个非常具体的 HTML/CSS 和/或 JS 问题。我在 this fiddle here 创建了一个示例显示问题。 我有一个可滚动的 div,它是一个表的父级: ...我的表格行之一包
我的 jar 文件中打包了一个 exe,我试图将它复制到一个临时位置,以便我可以使用 Desktop.browse() 运行它,为此我设置了一个使用 class.getResourceAsStream
您好,我对这段代码有疑问。我的问题是第一个 console.log(smile_per_sec) 给了我需要的值,但是第二个给了我声明变量时给它的值。 $.getJSON( twitter
我必须更改标记弹出窗口的默认大小以容纳我想放入其中的数据。我更改了一些 map 设置,因此当用户将其拖出 View 时,它总是会弹回最大范围。我遇到的问题是,对于靠近边缘的标记,当它的弹出窗口打开时,
我是一名优秀的程序员,十分优秀!