我正在使用MDBG示例制作托管.NET调试器。它适用于简单的场景,但在发生方法重写时会出现问题。最关键的部分是yield方法和异步方法。
我已经就这些问题提出了更为笼统的问题question。 现在我想专注于局部变量解析。 请考虑代码:
using System;
using System.Threading.Tasks;
class C
{
public static void Main() {
var instance = new Instance();
instance.Start().Wait();
}
}
class Instance
{
public static async Task F() { for(var i=0; i<100; i++) { Console.WriteLine(i); await Task.Delay(100); } }
public async Task Start() {
var z = "test";<------- Breakpoint
var x = 10;
await F();
}
}
当调试器到达断点时,我查询调试器以获取局部变量,唯一的变量是this
。变量x
和z
在生成的结构中悬挂,无法直接解析。
所以问题是:如何在yield方法和异步方法中调试局部变量期间解决?
在对我之前的问题的评论中,@ Brian Reichle给了我一些提示,告诉我如何在现有变量和提升变量之间进行映射。
在探索SymAttribute和Roslyn源代码时,我得出的结论是,它并没有直接存储它们之间的映射。 SymAttribute
用于获取CustomDebugInfoRecord
,它存储此信息的一部分(来自Roslyn的Used Pdb2Xml库来生成它):
<method containingType="Instance+<Start>d__1" name="MoveNext">
<customDebugInfo>
<forward declaringType="C" methodName="Main" />
<hoistedLocalScopes>
<slot startOffset="0x0" endOffset="0xcc" />
<slot startOffset="0x0" endOffset="0xcc" />
</hoistedLocalScopes>
<encLocalSlotMap>
<slot kind="27" offset="0" />
<slot kind="33" offset="161" />
<slot kind="temp" />
<slot kind="temp" />
</encLocalSlotMap>
</customDebugInfo>
<sequencePoints>
<entry offset="0x0" hidden="true" document="1" />
<entry offset="0x7" hidden="true" document="1" />
<entry offset="0xe" startLine="16" startColumn="37" endLine="16" endColumn="38" document="1" />
<entry offset="0xf" startLine="17" startColumn="14" endLine="17" endColumn="29" document="1" />
<entry offset="0x1a" startLine="18" startColumn="14" endLine="18" endColumn="35" document="1" />
<entry offset="0x26" startLine="19" startColumn="14" endLine="19" endColumn="25" document="1" />
<entry offset="0x2e" startLine="19" startColumn="25" endLine="19" endColumn="46" document="1" />
<entry offset="0x3a" startLine="20" startColumn="14" endLine="20" endColumn="24" document="1" />
<entry offset="0x45" hidden="true" document="1" />
<entry offset="0xa0" hidden="true" document="1" />
<entry offset="0xb8" startLine="21" startColumn="11" endLine="21" endColumn="12" document="1" />
<entry offset="0xc0" hidden="true" document="1" />
</sequencePoints>
<asyncInfo>
<kickoffMethod declaringType="Instance" methodName="Start" />
<await yield="0x57" resume="0x72" declaringType="Instance+<Start>d__1" methodName="MoveNext" />
</asyncInfo>
</method>
因此,我现在可以看到解决提升变量的唯一方法是:
this.generatedStructureName
x
变量翻译为<x>5__2
这种做法看起来并不正确,我不确定它是否会成功,但这是我现在唯一能想到的。 还有其他可能解决这个问题吗? VisualStudio如何处理它?</ p>
我创建了一个小型仓库来重现问题here
答案 0 :(得分:1)
好吧,我还没有在这里或在msdn论坛上发现任何人会告诉我VS算法是如何工作的,但是我发现 SharpDevelop 支持异步方法的变量解析。令人惊讶的是,它使用了与我在我的问题中描述的类似的算法:只解析提升的字段名称。
相关来源可以在gitHub上使用here,如果其他人遇到类似的问题而且会被卡住。不过,我不认为这是一个很好的解决方案,并希望有更好的方法来解决这个问题......