调用堆栈不说“你从哪里来”,而是说“你下一步要去哪里”?

2024-04-01

在上一个问题中(获取对象调用层次结构 https://stackoverflow.com/questions/6583883/get-object-call-hierarchy), 我有这个有趣的答案 https://stackoverflow.com/questions/6583883/get-object-call-hierarchy#comment7766834_6585089:

调用堆栈不会告诉您您来自哪里。它是告诉你下一步要去哪里。

据我所知,当到达函数调用时,程序通常会执行以下操作:

  1. In calling code:

    • 存储返回地址(在调用堆栈上)
    • 保存寄存器的状态(在调用堆栈上)
    • 写入将传递给函数的参数(在调用堆栈或寄存器中)
    • 跳转到目标函数

  2. In called目标代码:

    • 检索存储的变量(如果需要)

  3. 退货流程:撤消调用该函数时所做的操作,即展开/弹出调用堆栈:

    • 从调用堆栈中删除局部变量
    • 从调用堆栈中删除函数变量
    • 恢复寄存器状态(我们之前存储的状态)
    • 跳转到返回地址(我们之前存储的地址)

问题:

这怎么能被视为某事“告诉你下一步要去哪里”而不是“告诉你你从哪里来”?

C# 的 JIT 或 C# 运行时环境中是否有某些东西使调用堆栈的工作方式不同?

感谢您对有关调用堆栈描述的文档的任何指点 - 有大量有关传统调用堆栈如何工作的文档。


你自己已经解释过了。 “返回地址”的定义告诉你你下一步要去哪里.

不要求放入堆栈的返回地址是方法内部的地址called你现在使用的方法。它通常是的,这确实使调试变得更容易。但没有一个要求返回地址是调用者内部的地址。优化器被允许——有时确实——修改返回地址,如果这样做可以使程序更快(或更小,或者无论它优化的目的是什么)而不改变其含义。

堆栈的目的是确保当该子例程完成时,它是延续——接下来发生的事情——是正确的。堆栈的目的不是告诉你你从哪里来。它通常这样做是一个令人高兴的意外。

此外:堆栈只是概念的实现细节延续 and 激活。不要求这两个概念由同一个堆栈实现;可能有两个堆栈,一个用于激活(局部变量),一个用于继续(返回地址)。这种架构显然更能抵抗恶意软件的堆栈粉碎攻击,因为返回地址远离数据。

更有趣的是,根本不需要有任何堆栈!我们使用调用堆栈来实现延续,因为它们对于我们通常执行的编程类型:基于子例程的同步调用很方便。我们可以选择将 C# 实现为“Continuation Passing Style”语言,其中延续实际上是reified http://blogs.msdn.com/b/ericlippert/archive/2009/04/17/five-dollar-words-for-programmers-part-five-reification.aspx as an 堆上的对象,不作为一堆字节压入一百万字节的系统堆栈。然后该对象从一个方法传递到另一个方法,其中没有一个使用任何堆栈。 (然后通过将每个方法分解为可能的多个委托来具体化激活,每个委托都与一个激活对象关联。)

在连续传递风格中,根本没有堆栈,也根本无法判断你来自哪里;延续对象没有该信息。它只知道你下一步要去哪里。

这似乎是一个冠冕堂皇的理论胡言乱语,但是我们本质上是将 C# 和 VB 变成连续传递风格的语言在下一个版本中;即将到来的“异步”功能只是简单伪装的延续传递风格。在下一个版本中,如果您使用异步功能,您实际上将放弃基于堆栈的编程;无法查看调用堆栈并知道如何到达这里,因为堆栈经常是空的。

对于很多人来说,将延续具体化为调用堆栈以外的东西是一个很难理解的想法;这当然是为了我。但一旦你明白了,你就会明白它的意思。作为一个温和的介绍,这里有我写的一些关于这个主题的文章:

CPS 简介,并附有 JScript 示例:

http://blogs.msdn.com/b/ericlippert/archive/2005/08/08/recursion-part-four-continuation-passing-style.aspx http://blogs.msdn.com/b/ericlippert/archive/2005/08/08/recursion-part-four-continuation-passing-style.aspx

http://blogs.msdn.com/b/ericlippert/archive/2005/08/11/recursion-part- Five-more-on-cps.aspx http://blogs.msdn.com/b/ericlippert/archive/2005/08/11/recursion-part-five-more-on-cps.aspx

http://blogs.msdn.com/b/ericlippert/archive/2005/08/15/recursion-part-six-making-cps-work.aspx http://blogs.msdn.com/b/ericlippert/archive/2005/08/15/recursion-part-six-making-cps-work.aspx

这里有十几篇文章,首先深入研究 CPS,然后解释这一切如何与即将到来的“异步”功能一起工作。从底部开始:

http://blogs.msdn.com/b/ericlippert/archive/tags/async/ http://blogs.msdn.com/b/ericlippert/archive/tags/async/

支持延续传递风格的语言通常有一个神奇的控制流原语,称为“使用当前延续进行调用”,简称为“call/cc”。在这个 stackoverflow 问题中,我解释了“await”和“call/cc”之间的细微区别:

c# 5.0 中的新异步功能如何通过 call/cc 实现? https://stackoverflow.com/questions/4070237/how-could-the-new-async-feature-in-c-5-0-be-implemented-with-call-cc

要获取官方“文档”(一堆白皮书)、C# 和 VB 新“异步等待”功能的预览版以及支持问答论坛,请访问:

http://msdn.com/vstudio/async http://msdn.com/vstudio/async

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

调用堆栈不说“你从哪里来”,而是说“你下一步要去哪里”? 的相关文章

  • IEnumerable 的 String.Join(string, string[]) 的类似物

    class String包含非常有用的方法 String Join string string 它从数组创建一个字符串 用给定的符号分隔数组的每个元素 但一般来说 它不会在最后一个元素之后添加分隔符 我将它用于 ASP NET 编码 以用
  • 叮当错误?命名空间模板类的朋友

    以下代码在 clang 下无法编译 但在 gcc 和 VS 下可以编译 template
  • MFC CList 支持复制分配吗?

    我在 MSVC 中查找了 CList 定义afxtempl h http www cppdoc com example mfc classdoc MFC AFXTEMPL H html并记录在MSDN http msdn microsoft
  • 异常堆栈跟踪不显示抛出异常的位置

    通常 当我抛出异常 捕获它并打印出堆栈跟踪时 我会看到抛出异常的调用 导致该异常的调用 导致该异常的调用that 依此类推回到整个程序的根 现在它只向我显示异常所在的调用caught 而不是它所在的地方thrown 我不明白是什么改变导致了
  • 如果 JSON.NET 中的值为 null 或空格,则防止序列化

    我有一个对象需要以这样的方式序列化 即 null 和 空白 空或只是空格 值都不会序列化 我不控制对象本身 因此无法设置属性 但我知道所有属性都是字符串 环境NullValueHandling显然 忽略 只能让我找到解决方案的一部分 它 似
  • 司机和提供商之间的区别

    数据库中的驱动程序和提供程序有什么区别 有没有解释一下 不胜感激 样本 ADO NET driver for MySQL vs providerName System Data EntityClient 来自 MSDN 论坛 驱动程序是安装
  • 将设置函数(setter)标记为 constexpr 的目的是什么? [复制]

    这个问题在这里已经有答案了 我无法理解将 setter 函数标记为的目的constexpr 自 C 14 起这是允许的 我的误解来自以下情况 我使用 constexpr c tor 声明一个类 并且我将通过创建该类的 constexpr 实
  • C# 处理标准输入

    我目前正在尝试通过命令行断开与网络文件夹的连接 并使用以下代码 System Diagnostics Process process2 new System Diagnostics Process System Diagnostics Pr
  • .NET 程序集差异/比较工具 - 有什么可用? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我希望能够在两个程序集之间进行代码级差异 Reflector 的 Diff 插件是迄今为止我发现的最接
  • 带有运算符语法的错误消息,但不带有函数语法的错误消息

    为什么我在调用 unary 时收到错误消息 使用运算符语法 如果我用函数语法调用它就可以了 现场演示 https godbolt org z j7AbeQ template
  • 为什么需要数字后缀?

    C 语言 我确信还有其他语言 需要在数字文字末尾添加后缀 这些后缀指示文字的类型 例如 5m是一个小数 5f是一个浮点数 我的问题是 这些后缀真的有必要吗 或者是否可以从上下文中推断出文字的类型 例如 代码decimal d 5 0应该推断
  • 将日期时间转换为指定格式

    我有这个日期格式yy MM dd HH mm ss ex 12 02 21 10 56 09 问题是 当我尝试使用以下代码将其转换为不同格式时 CDate 12 02 21 10 56 09 ToString MMM dd yyyy HH
  • Resharper:IEnumerable 的可能多重枚举

    我正在使用新的 Resharper 版本 6 在我的代码中的几个地方 它给一些文本加了下划线 并警告我可能存在IEnumerable 可能的多重枚举 我理解这意味着什么 并在适当的情况下采纳了建议 但在某些情况下 我不确定这实际上是一个大问
  • 为什么不能调用带有 auto& 参数的 const mutable lambda?

    include
  • 如何在 C# 中获取 Json 数组?

    我有一个像这样的 Json 字符串 我想将它加载到 C 数组中 当我尝试这样做时 我收到异常 我的字符串 customerInformation customerId 123 CustomerName Age 39 Gender Male
  • 浮点字节序?

    我正在为实时海上模拟器编写客户端和服务器 并且由于我必须通过套接字发送大量数据 因此我使用二进制数据来最大化可以发送的数据量 我已经了解整数字节顺序以及如何使用htonl and ntohl为了规避字节顺序问题 但我的应用程序与几乎所有模拟
  • Xamarin.Forms UWP 项目中标题栏和选项卡之间令人恼火的空白

    我几乎是新手Xamarin Forms我正在开发一个相当简单的跨平台应用程序 该应用程序在 Android 中显示得足够好 但在 UWP 中却出现了一个愚蠢的空白 该项目由一个 TabbedPage 组成 其中包含 4 个 Navigati
  • 调试VS 2005提示“操作不支持”

    我一直在调试 VS 2005 并将 启动外部程序 设置为 C Program Files Microsoft Visual Studio 10 0 Common7 IDE devenv exe 但按 F5 后出现此错误 尝试运行项目时出错
  • C++ Boost ASIO 简单的周期性定时器?

    我想要一个非常简单的周期性计时器每 50 毫秒调用我的代码 我可以创建一个始终休眠 50 毫秒的线程 但这很痛苦 我可以开始研究用于制作计时器的 Linux API 但它不可移植 I d like使用升压 我只是不确定这是否可能 boost
  • 嵌入式二进制资源 - 如何枚举嵌入的图像文件?

    我按照中的说明进行操作这本书 http www apress com book view 9781430225492 关于资源等的章节 我不太明白的是 如何替换它 images Add new BitmapImage new Uri Ima

随机推荐

  • \bin 中插入不需要的 SQLite

    我正在使用 Visual Studio 2010 并使用 Web 部署将 Net MVC 站点提升到特定环境 我安装了 Elmah 它在我的 DEV 环境中运行得很好 但是当我推送 TEST 时 我遇到了异常 因为 SQLite 不是一种好
  • Django - 使用子对象过滤查询集(ForeignKey)

    我有 3 个模型 其中 2 个对应第一个模型 class Parent models Model name models CharField class Child1 models Model parent models ForeignKe
  • C 语言中的“{0}”是什么?

    什么是char buf MAXDATASIZE 0 s 0 means 试图打印它 但它什么也没打印 include
  • 检查用户是否使用兼容模式的 IE

    我正在寻找一些代码 PHP 或 JavaScript 可以很好地检查查看页面的用户是否使用兼容模式 然后我可以使用该代码执行一些条件语句 或者基本上给他们一个通知以将其关闭 强迫他们 这将禁用兼容性视图 除非用户随后通过进入开发人员工具并进
  • Spring Security:多个ThreadLocals中有相同的SecurityContext实例,它是如何工作的?

    我有一些关于 Spring Security 3 0 5 和 SecurityContext 的问题 首先 我尝试总结一下我所知道的 SecurityContextHolder 存储 SecurityContext 在Request之间 S
  • 多个 socket.io 服务器共享单个 HTTP/S 服务器

    使用 ws Node js WebSocket 库 可以有多个服务器共享单个 HTTP S 服务器 https github com websockets ws multiple servers sharing a single https
  • iPhone Web 应用程序 - 接听电话时会话和当前 URL 丢失

    我有一个多页面网站 旨在作为 iPhone 上的网络应用程序运行 它具有通常的
  • 如何将 PIL.ImageTk.PhotoImage 保存为 jpg

    我想将 PIL ImageTk PhotoImage 保存到文件中 我的方法是创建一个 打开 文件并调用 写入 方法 但它不起作用 因为我不知道如何从对象获取字节数组 def store temp image data image new
  • 多部分/替代子类型,客户端何时使用它?

    为什么网络邮件 如 Gmail 使用以下方式发送 MIME 消息多部分 替代子类型 当用 HTML 编写时 而其他人将 HTML 作为 MIME 发送 其中包含文本 html 部分 不使用替代子类型 The 第5 1 4节 https ww
  • 复杂类型作为数组索引

    array 对象 obj other obj PHP 数组仅适用于标量数据类型 如 int string float boolean null 的索引 我不能像其他语言一样使用对象作为数组索引吗 那么如何实现对象 gt 对象映射呢 虽然我在
  • 在 Rust 中将递归函数转换为迭代器的技术?

    我正在努力将一个简单的递归函数变成一个简单的迭代器 问题在于递归函数在其局部变量和调用堆栈中维护状态 将其转换为 Rust 迭代器意味着基本上将所有函数状态外部化为某些自定义迭代器结构上的可变属性 这是一个相当混乱的尝试 在 javascr
  • Git Pull Force 覆盖本地文件

    Git 拉力 git 将分支重置到原点 或者换句话说 拉取远程分支以覆盖本地分支 似乎是一个被广泛搜索的功能 尽管本地搜索量很少下降 但人们的兴趣却越来越大 对于不断壮大的团队和不断增加的开发人员数量来说 这绝对有意义 目前 最短的工作解决
  • 如何将我的 Magento 迷你搜索表单移动到模板标题中的另一个位置?

    我正在构建我的第一个自定义 Magento 主题 虽然进展缓慢 但是is去 我去掉了主页上最初保存迷你搜索表单的栏 而是想将搜索表单放入新标题中 这是我的标题的代码header phtml div a href title class lo
  • Kafka应用程序启动时无法配置主题,但稍后可以通信

    我们有一个使用 spring kafka 2 2 5 RELEASE 的 Spring Boot 应用程序 在启动时总是出现此错误 Could not configure topics org springframework kafka K
  • 如何对齐指针

    如何将指针与 16 字节边界对齐 我找到了这段代码 不确定是否正确 char p malloc 1024 if unsigned long p 16 0 unsigned char chpoint unsigned char p chpoi
  • pandas 在多列上搜索子字符串

    我有一个 df 这样 c name f name 0 abc abc12 1 xyz abc1 2 mnq mnq2 目标是在两列中找到一个子字符串并知道它属于哪一列 优先选择应该是c name 就像子字符串在两列中一样c name获得优先
  • 学习 XQuery 的简单工具? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我开始玩XQuery 在 w3schools 1 上 这是一个很好的教程 我只是遇到一些问题 我无法测试网站上的内容 我在网上找到了一个X
  • **正确地**从字符串创建 lambda 函数

    给定一个字符串 例如 2 i j lt 100 我想生成相应的lambda函数 fn lambda i j 2 i j lt 100 我可以这样做eval 但我正在寻找一种不那么邪恶的方法 我已经发现 import ast f ast La
  • Firebase 重置密码链接不起作用

    我正在使用 firebase 对我的 Android 应用程序中的用户进行身份验证 我为用户提供了在登录窗口中重置密码的选项 当用户单击按钮时 它会成功发送电子邮件 但是 当用户单击链接时 它总是显示 再次尝试重置密码 您重置密码的请求已过
  • 调用堆栈不说“你从哪里来”,而是说“你下一步要去哪里”?

    在上一个问题中 获取对象调用层次结构 https stackoverflow com questions 6583883 get object call hierarchy 我有这个有趣的答案 https stackoverflow com