Tôi đang tạo một trình gỡ lỗi .NET được quản lý bằng mẫu MDBG. Nó hoạt động cho các tình huống đơn giản, nhưng có vấn đề khi viết lại phương thức xảy ra. Hầu hết các bộ phận quan trọng là phương pháp lợi nhuận và phương pháp không đồng bộ.Công cụ gỡ lỗi. Phương pháp viết lại, biến cục bộ và biến phân giải
Tôi đã hỏi tổng quát hơn question về các sự cố này. Bây giờ tôi muốn tập trung vào độ phân giải biến cục bộ. Hãy xem xét các mã:
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();
}
}
Khi debugger đạt Breakpoint tôi truy vấn gỡ rối để có được các biến cục bộ và biến duy nhất là this
. Các biến số x
và z
được lưu trữ trên cấu trúc được tạo và không thể được giải quyết trực tiếp .
Câu hỏi đặt ra là: Cách giải quyết trong khi gỡ lỗi biến cục bộ trong phương thức lợi nhuận và phương pháp không đồng bộ?
Trong nhận xét cho câu hỏi trước đây của tôi @Brian Reichle đã cho tôi một số gợi ý làm cách nào tôi có thể lấy ánh xạ giữa biến hiện tại và được đặt trong danh sách. Khám phá SymAttribute và nguồn Roslyn Tôi đi đến kết luận rằng nó không trực tiếp lưu trữ ánh xạ giữa chúng. SymAttribute
được sử dụng để có được CustomDebugInfoRecord
, mà các cửa hàng một phần của thông tin này (sử dụng thư viện Pdb2Xml từ Roslyn để tạo ra nó):
<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>
Vì vậy, cách duy nhất tôi có thể nhìn thấy bây giờ để giải quyết biến kéo lên là:
- Kiểm tra xem phương pháp có được viết lại hay không.
- Đối với phương thức như vậy, hãy truy cập asyncInfo và thấy nó đang chờ khai báoType. Nó cung cấp cho tên của cấu trúc được tạo ra và nơi các biến được hoisted.
- Resolve
this.generatedStructureName
- Roslyn mã nguồn tiết lộ naming conventions for hoisted variables, có thể được sử dụng để dịch
x
biến thành<x>5__2
Cách tiếp cận này không có vẻ đúng và tôi không chắc chắn nếu nó bao giờ sẽ làm việc ra, nhưng đó là điều duy nhất tôi có thể nghĩ đến bây giờ. Có khả năng nào khác để giải quyết vấn đề này không? Làm thế nào để VisualStudio giải quyết nó?
Tôi đã tạo một repo nhỏ để tạo lại vấn đề here