且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

调用堆栈不说"你来自哪里"但是"你要去哪里,下一个"?

更新时间:2022-04-23 16:58:59

您已经自己解释它。在返回地址的定义告诉你的你要去哪里,下一个的。

You've explained it yourself. The "return address" by definition tells you where you are going next.

有任何的被放在堆栈上的返回地址是的该方法被称为内部的地址不要求的你在现在的方法。它的一般的是,这肯定更容易调试。但还没有一个的要求的,该返回地址是呼叫者内的地址。优化允许 - 有时是 - 渣土的返回地址,如果这样做使程序速度更快(或更小,或不管它是优化),而不改变其意义

There is no requirement whatsoever that the return address that is put on the stack is an address inside the method that called the method you're in now. It typically is, which sure makes it easier to debug. But there is not a requirement that the return address be an address inside the caller. The optimizer is permitted to -- and sometimes does -- muck with the return address if doing so makes the program faster (or smaller, or whatever it is optimizing for) without changing its meaning.

堆的目的是为了确保当这个子程序完成后,它的的继续的 - 接下来会发生什么 - 是正确的。堆栈的目的不是要告诉你,你来自哪里。它通常这样做是一个快乐的意外。

The purpose of the stack is to make sure that when this subroutine finishes, it's continuation -- what happens next -- is correct. The purpose of the stack is not to tell you where you came from. That it usually does so is a happy accident.

此外:堆栈中的概念,只是实现的细节的继续激活的。没有这两个概念由相同的栈中实现的要求;可能有两个堆栈,一个用于激活(局部变量),一个用于继续(返回地址)。这样的架构显然更耐堆栈被恶意砸攻击,因为返回地址是远不数据。

Moreover: the stack is just an implementation detail of the concepts of continuation and activation. There is no requirement that both concepts be implemented by the same stack; there could be two stacks, one for activations (local variables) and one for continuation (return addresses). Such architectures are obviously much more resistant to stack smashing attacks by malware because the return address is nowhere near the data.

更有趣的是,不要求有任何堆了!我们使用调用栈实现的延续,因为他们是方便了种编程,我们通常做的:子程序为基础的同步调用。我们可以选择实现C#作为一个延续传递风格的语言,在这里延续实际上是reified作为堆的的的的对象,而不是的一堆字节推一百万字节的系统堆栈的。然后该对象被传递围绕从法法,其中没有使用任何堆栈。 (启动被打破每种方法成可能是许多代表,每一个都与激活对象相关联,然后具体化。)

More interestingly, there is no requirement that there be any stack at all! We use call stacks to implement continuation because they are convenient for the kind of programming we typically do: subroutine-based synchronous calls. We could choose to implement C# as a "Continuation Passing Style" language, where the continuation is actually reified as an object on the heap, not as a bunch of bytes pushed on a million byte system stack. That object is then passed around from method to method, none of which use any stack. (Activations are then reified by breaking each method up into possibly many delegates, each of which is associated with an activation object.)

在延续传递方式目前根本没有堆栈,没有办法都没有告诉你来自哪里;延续对象没有这些信息。它只知道你要去哪里,下一个。

In continuation passing style there simply is no stack, and no way at all to tell where you came from; the continuation object does not have that information. It only knows where you are going next.

这似乎是一个冠冕堂皇的理论魔神,但是的我们基本上正在C#和VB为延续传递风格的语言的在未来的版本;即将到来的异步的功能只是延续传送风格在薄薄的伪装。在接下来的版本中,如果使用异步功能,您将基本被放弃基于堆栈的编程;就没有办法看调用堆栈,并知道你是怎么来到这里,因为堆栈会经常是空的。

This might seem to be a highfalutin theoretical mumbo jumbo, but we essentially are making C# and VB into continuation passing style languages in the next version; the coming "async" feature is just continuation passing style in a thin disguise. In the next version, if you use the async feature you will essentially be giving up stack-based programming; there will be no way to look at the call stack and know how you got here, because the stack will frequently be empty.

物化为比调用堆栈其他东西延续是有很多人来解决他们的思想硬的想法;它肯定是我。但是,一旦你得到它,它只是点击和非常有意义。一个温柔的介绍,这里有一些文章中,我已经写了关于这个问题的:

Continuations reified as something other than a call stack is a hard idea for a lot of people to get their minds around; it certainly was for me. But once you get it, it just clicks and makes perfect sense. For a gentle introduction, here are a number of articles I've written on the subject:

这是介绍CPS,举例在JScript中:

An introduction to CPS, with examples in 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/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

下面是开始这样做更深的下潜到CPS一打文章,然后再解释这一切工作与即将到来的异步功能。从底部开始:

Here are a dozen articles that start by doing a deeper dive into CPS, and then explain how this all works with the coming "async" feature. Start from the bottom:

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

这是支持延续传递风格往往有一个神奇的控制流程被称为原始语言与当前的延续呼叫或呼叫/ CC的简称。在这个计算器的问题,我解释之间的差异微不足道等待和呼叫/ CC:

Languages that support continuation passing style often have a magic control flow primitive called "call with current continuation", or "call/cc" for short. In this *** question, I explain the trivial difference between "await" and "call/cc":

How可以在C#5.0的通话/立方厘米实施新的异步功能?

要得到你的手官方的文档(一堆白皮书),和C#的preVIEW释放和VB的新的异步等待功能,加上支持Q&放一个论坛; A,去

To get your hands on the official "documentation" (a bunch of white papers), and a preview release of C# and VB's new "async await" feature, plus a forum for support Q&A, go to:

http://msdn.com/vstudio/async