如何通过堆栈跟踪访问本地人? (模仿动态范围) [英] How to access locals through stack trace? (Mimicking dynamic scope)

查看:137
本文介绍了如何通过堆栈跟踪访问本地人? (模仿动态范围)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

尽管它可能在运行时编译C#code,这是不可能的,包括和运行生成code在当前范围内。相反,所有的变量都必须传递明确的参数。

与Python等动态编程语言相比,人们可以从来没有真正复制的完整的行为评估(如本例)。

  X = 42
打印(EVAL(X + 1))#打印43
 

问题

所以我的问题是(不管它实际上是有益的;))是否有可能通过使用的反射

模仿动态范围在.NET。

由于.NET为我们提供了 Diagnostics.StackTrace 类,它允许我们检查调用方法,这个问题可以归结为以下几点:(如何)是否有可能可靠地访问调用方法的当地人

是否堆栈跟踪信息为我们提供足够的信息来计算内存偏移或者是禁止在管理code反正这样的事情?

就是这样code某种程度上可能吗?

 无效美孚(){
   INT X = 42;
   Console.WriteLine(酒吧());
}

INT酒吧(){
   返回(int)的(DynamicScope.Resolve(×)); //将访问Foo的X = 42
}
 

解决方案

这是不可能的。在编译.NET code(中间语言),变量重新presented简单地在栈上的索引。例如 ldloc 指令,它加载一个变量的值,只有一个无符号INT16 值作为参数。可能有一些方法来做到这一点在调试模式下编译的应用程序(毕竟,调试应用程序时,Visual Studio中创建),但它不能在一般的工作。

在Phalanger(PHP编译器,.NET,而我部分参与),这不得不以某种方式解决,因为PHP语言有评估(它不吨需要提供的动态作用域的,但它需要通过名称访问变量)。因此,Phalanger检测如果函数包含任何使用评估的,如果是的话,它存储所有的变量在词典<字符串,对象> ,然后传递到评估功能(这样它可以读出他们的名字变量)。这恐怕是这样做的唯一途径...

Background

Even though it's possible to compile C# code at runtime, it's impossible to include and run the generated code in the current scope. Instead all variables have to be passed as explicit parameters.

Compared with dynamic programming languages like Python, one could never truly replicate the complete behaviour of eval (as in this example).

x = 42
print(eval("x + 1")) # Prints 43

The question

So my question is (regardless if it's actually useful ;)) whether it's possible to mimic dynamic scope in .NET through the use of reflection.

Since .NET provides us with the Diagnostics.StackTrace class which allows us to inspect the calling methods, this question boils down to the following: (How) is it possible to reliably access the locals of calling methods?

Does the stack trace provide us with enough information to compute the memory offsets or are such things forbidden in managed code anyway?

Is such code somehow possible?

void Foo() {
   int x = 42;
   Console.WriteLine(Bar());
}

int Bar() {
   return (int)(DynamicScope.Resolve("x")); // Will access Foo's x = 42
}

解决方案

This isn't possible. In the compiled .NET code (intermediate language), variables are represented simply as indices on the stack. For example the ldloc instruction, which loads a value of a variable takes only an unsigned int16 value as the parameter. There may be some way to do this for applications compiled in debug mode (after all, when debugging application, Visual Studio does that), but it cannot work in general.

In Phalanger (PHP compiler for .NET, which I'm partly involved in), this had to be somehow solved, because PHP language has eval (it doesn't need to provide dynamic scoping, but it needs to access variables by name). So, Phalanger detects if a function contains any use of eval and if it does, it stores all variables in Dictionary<string, object>, which is then passed to the eval function (so that it can read variables by their name). I'm afraid this is the only way to do this...

这篇关于如何通过堆栈跟踪访问本地人? (模仿动态范围)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆