How to access locals through stack trace? (Mimicking dynamic scope)
即使可以在运行时编译C代码,也不可能在当前范围内包含和运行生成的代码。相反,所有变量都必须作为显式参数传递。
与Python等动态编程语言相比,我们永远无法真正复制
1 2 | x = 42 print(eval("x + 1")) # Prints 43 |
问题
所以我的问题是(不管它是否真的有用;)是否可以通过反射来模拟.NET中的动态范围。
由于.NET为我们提供了允许我们检查调用方法的
堆栈跟踪是否为我们提供足够的信息来计算内存偏移量,或者在托管代码中是否仍然禁止这样的操作?
这样的代码有可能吗?
1 2 3 4 5 6 7 8 | void Foo() { int x = 42; Console.WriteLine(Bar()); } int Bar() { return (int)(DynamicScope.Resolve("x")); // Will access Foo's x = 42 } |
号
So my question is whether it's possible to mimic dynamic scope in .NET through the use of reflection.
号
反射允许对程序集元数据中表示的项进行运行时操作。
局部变量不是程序集元数据中表示的项。
因此,你的问题的答案是"不"。
(How) is it possible to reliably access the locals of calling methods?
号
访问调用方法的局部变量的设备称为"调试器"。所以问题的答案是"给自己写一个调试器"。
注意,在代码优化的世界中,调试器不能可靠地访问局部变量。局部变量可以被优化,抖动可以生成代码,对两个不同的局部变量使用相同的寄存器,堆栈帧可以在尾部调用期间重复使用,等等。当然,最好有一个PDB文件告诉调试器与每个堆栈帧位置相关联的名称是什么。
方法需要做的是将自定义调试器作为新进程启动,然后等待调试器向其发送消息。然后,调试器将挂起原始进程的线程,询问堆栈帧,然后恢复进程的线程。然后它会将消息发送到包含您发现的信息的调试对象。由于调试对象处于等待状态,等待消息,因此它将恢复其业务。
如果您想要的是一种进程内的"eval"功能,那么可以考虑jscript.net,一种专门为这种功能设计的语言。
这是不可能的。在编译的.NET代码(中间语言)中,变量简单地表示为堆栈上的索引。例如,加载变量值的
在phalanger(我部分参与的php编译器for.net)中,必须以某种方式解决这个问题,因为php语言有