Đầu tiên, tôi xin lỗi về độ dài của câu hỏi này.
Tôi là tác giả của IronScheme . Gần đây tôi đã làm việc chăm chỉ để phát ra thông tin gỡ lỗi đàng hoàng, để tôi có thể sử dụng trình gỡ lỗi .NET 'bản địa'.
Trong khi điều này đã thành công một phần, tôi đang gặp phải một số vấn đề về mọc răng.
Vấn đề đầu tiên liên quan đến bước.
Do lược đồ là ngôn ngữ biểu thức, mọi thứ có xu hướng được gói trong ngoặc đơn, không giống như các ngôn ngữ .NET chính dường như là câu lệnh (hoặc dòng) dựa trên.
Mã ban đầu (Scheme) trông giống như:
(define (baz x)
(cond
[(null? x)
x]
[(pair? x)
(car x)]
[else
(assertion-violation #f "nooo" x)]))
Tôi có mục đích đặt ra từng biểu thức trên một dòng mới.
Mã được phát ra biến đổi thành C # (thông qua ILSpy) trông giống như:
public static object ::baz(object x)
{
if (x == null)
{
return x;
}
if (x is Cons)
{
return Builtins.Car(x);
}
return #.ironscheme.exceptions::assertion-violation+(
RuntimeHelpers.False, "nooo", Builtins.List(x));
}
Như bạn thấy, khá đơn giản.
Lưu ý: Nếu mã được chuyển thành biểu thức có điều kiện (? :) trong C #, toàn bộ điều sẽ chỉ là một bước gỡ lỗi, hãy ghi nhớ điều đó.
Đây là đầu ra IL với số nguồn và số dòng:
.method public static object '::baz'(object x) cil managed
{
// Code size 56 (0x38)
.maxstack 6
.line 15,15 : 1,2 ''
//000014:
//000015: (define (baz x)
IL_0000: nop
.line 17,17 : 6,15 ''
//000016: (cond
//000017: [(null? x)
IL_0001: ldarg.0
IL_0002: brtrue IL_0009
.line 18,18 : 7,8 ''
//000018: x]
IL_0007: ldarg.0
IL_0008: ret
.line 19,19 : 6,15 ''
//000019: [(pair? x)
.line 19,19 : 6,15 ''
IL_0009: ldarg.0
IL_000a: isinst [IronScheme]IronScheme.Runtime.Cons
IL_000f: ldnull
IL_0010: cgt.un
IL_0012: brfalse IL_0020
IL_0017: ldarg.0
.line 20,20 : 7,14 ''
//000020: (car x)]
IL_0018: tail.
IL_001a: call object [IronScheme]IronScheme.Runtime.Builtins::Car(object)
IL_001f: ret
IL_0020: ldsfld object
[Microsoft.Scripting]Microsoft.Scripting.RuntimeHelpers::False
IL_0025: ldstr "nooo"
IL_002a: ldarg.0
IL_002b: call object [IronScheme]IronScheme.Runtime.Builtins::List(object)
.line 22,22 : 7,40 ''
//000021: [else
//000022: (assertion-violation #f "nooo" x)]))
IL_0030: tail.
IL_0032: call object [ironscheme.boot]#::
'ironscheme.exceptions::assertion-violation+'(object,object,object)
IL_0037: ret
} // end of method 'eval-core(033)'::'::baz'
Lưu ý: Để ngăn trình gỡ lỗi chỉ cần làm nổi bật toàn bộ phương thức, tôi tạo điểm nhập phương thức chỉ rộng 1 cột.
Như bạn có thể thấy, mỗi biểu thức ánh xạ chính xác đến một dòng.
Bây giờ vấn đề với bước (thử nghiệm trên VS2010, nhưng vấn đề tương tự / tương tự trên VS2008):
Đây là với IgnoreSymbolStoreSequencePoints
không áp dụng.
- Gọi baz với null arg, nó hoạt động chính xác. (null? x) theo sau là x.
- Gọi baz với Cons arg, nó hoạt động chính xác. (null? x) rồi (cặp? x) rồi (xe x).
- Gọi baz với arg khác, nó thất bại. (null? x) rồi (cặp? x) rồi (xe x) rồi (vi phạm khẳng định ...).
Khi nộp đơn IgnoreSymbolStoreSequencePoints
(theo khuyến nghị):
- Gọi baz với null arg, nó hoạt động chính xác. (null? x) theo sau là x.
- Gọi baz với Cons arg, nó thất bại. (null? x) sau đó (cặp? x).
- Gọi baz với arg khác, nó thất bại. (null? x) rồi (cặp? x) rồi (xe x) rồi (vi phạm khẳng định ...).
Tôi cũng thấy trong chế độ này, một số dòng (không được hiển thị ở đây) được tô sáng không chính xác, chúng bị tắt bởi 1.
Dưới đây là một số ý tưởng những gì có thể là nguyên nhân:
- Tailcalls nhầm lẫn trình gỡ lỗi
- Các vị trí chồng lấp (không hiển thị ở đây) gây nhầm lẫn cho trình gỡ lỗi (nó rất tốt khi đặt điểm dừng)
- ????
Vấn đề thứ hai, nhưng cũng nghiêm trọng là trình gỡ lỗi không phá được / chạm các điểm dừng trong một số trường hợp.
Nơi duy nhất mà tôi có thể khiến trình gỡ lỗi phá vỡ chính xác (và nhất quán), là tại điểm nhập phương thức.
Tình hình trở nên tốt hơn một chút khi IgnoreSymbolStoreSequencePoints
không được áp dụng.
Phần kết luận
Có thể là trình gỡ lỗi VS chỉ là lỗi đơn giản :(
Người giới thiệu:
Cập nhật 1:
Mdbg không hoạt động cho các cụm 64 bit. Vì vậy, đó là ra. Tôi không còn máy 32-bit để kiểm tra. Cập nhật: Tôi chắc chắn đây không phải là vấn đề lớn, có ai có cách khắc phục không? Chỉnh sửa: Có, ngớ ngẩn với tôi, chỉ cần bắt đầu mdbg dưới dấu nhắc lệnh x64 :)
Cập nhật 2:
Tôi đã tạo một ứng dụng C # và cố gắng phân tích thông tin dòng.
Phát hiện của tôi:
- Sau bất kỳ
brXXX
hướng dẫn nào, bạn cần phải có một điểm thứ tự (nếu không hợp lệ hay còn gọi là '#line hidden', phát ra anop
). - Trước bất kỳ
brXXX
hướng dẫn nào , hãy phát ra một '#line hidden' và anop
.
Áp dụng điều này, tuy nhiên không khắc phục được các vấn đề (một mình?).
Nhưng thêm vào sau đây, cho kết quả mong muốn :)
- Sau đó
ret
, phát ra một '#line ẩn' và anop
.
Đây là sử dụng chế độ IgnoreSymbolStoreSequencePoints
không được áp dụng. Khi áp dụng, một số bước vẫn bị bỏ qua :(
Đây là đầu ra IL khi ở trên đã được áp dụng:
.method public static object '::baz'(object x) cil managed
{
// Code size 63 (0x3f)
.maxstack 6
.line 15,15 : 1,2 ''
IL_0000: nop
.line 17,17 : 6,15 ''
IL_0001: ldarg.0
.line 16707566,16707566 : 0,0 ''
IL_0002: nop
IL_0003: brtrue IL_000c
.line 16707566,16707566 : 0,0 ''
IL_0008: nop
.line 18,18 : 7,8 ''
IL_0009: ldarg.0
IL_000a: ret
.line 16707566,16707566 : 0,0 ''
IL_000b: nop
.line 19,19 : 6,15 ''
.line 19,19 : 6,15 ''
IL_000c: ldarg.0
IL_000d: isinst [IronScheme]IronScheme.Runtime.Cons
IL_0012: ldnull
IL_0013: cgt.un
.line 16707566,16707566 : 0,0 ''
IL_0015: nop
IL_0016: brfalse IL_0026
.line 16707566,16707566 : 0,0 ''
IL_001b: nop
IL_001c: ldarg.0
.line 20,20 : 7,14 ''
IL_001d: tail.
IL_001f: call object [IronScheme]IronScheme.Runtime.Builtins::Car(object)
IL_0024: ret
.line 16707566,16707566 : 0,0 ''
IL_0025: nop
IL_0026: ldsfld object
[Microsoft.Scripting]Microsoft.Scripting.RuntimeHelpers::False
IL_002b: ldstr "nooo"
IL_0030: ldarg.0
IL_0031: call object [IronScheme]IronScheme.Runtime.Builtins::List(object)
.line 22,22 : 7,40 ''
IL_0036: tail.
IL_0038: call object [ironscheme.boot]#::
'ironscheme.exceptions::assertion-violation+'(object,object,object)
IL_003d: ret
.line 16707566,16707566 : 0,0 ''
IL_003e: nop
} // end of method 'eval-core(033)'::'::baz'
Cập nhật 3:
Vấn đề với 'bán sửa chữa' ở trên. Peverify báo cáo lỗi trên tất cả các phương pháp do nop
sau ret
. Tôi không hiểu vấn đề thực sự. Làm thế nào có thể nop
phá vỡ xác minh sau một ret
. Nó giống như mã chết (ngoại trừ mã KHÔNG phải là mã) ... Ồ, thử nghiệm vẫn tiếp tục.
Cập nhật 4:
Quay trở về nhà ngay bây giờ, xóa mã 'không thể xác minh', chạy trên VS2008 và mọi thứ còn tệ hơn rất nhiều. Có lẽ chạy mã không thể kiểm chứng vì mục đích gỡ lỗi thích hợp có thể là câu trả lời. Trong chế độ 'phát hành', tất cả đầu ra vẫn có thể kiểm chứng được.
Cập nhật 5:
Bây giờ tôi đã quyết định ý tưởng trên của tôi là lựa chọn khả thi duy nhất cho đến bây giờ. Mặc dù mã được tạo là không thể xác minh, tôi vẫn chưa tìm thấy bất kỳ VerificationException
. Tôi không biết tác động sẽ ra sao đối với người dùng cuối với kịch bản này.
Như một phần thưởng, vấn đề thứ hai của tôi cũng đã được giải quyết. :)
Đây là một chút screencast về những gì tôi đã kết thúc với. Nó đạt điểm dừng, thực hiện bước thích hợp (vào / ra / qua), v.v ... Tất cả trong tất cả, hiệu quả mong muốn.
Tôi, tuy nhiên, tôi vẫn không chấp nhận điều này như là cách để làm điều đó. Nó cảm thấy quá khó khăn với tôi. Có một xác nhận về vấn đề thực sự sẽ là tốt đẹp.
Cập nhật 6:
Chỉ cần thay đổi để kiểm tra mã trên VS2010, dường như có một số vấn đề:
Cuộc gọi đầu tiên bây giờ không bước chính xác. (khẳng định-vi phạm ...) bị đánh. Các trường hợp khác hoạt động tốt.Một số mã cũ phát ra các vị trí không cần thiết. Đã xóa mã, hoạt động như mong đợi. :)- Nghiêm trọng hơn, các điểm dừng không thành công trong lần gọi thứ hai của chương trình (sử dụng biên dịch trong bộ nhớ, lắp ráp kết xuất vào tệp dường như làm cho các điểm dừng vui vẻ trở lại).
Cả hai trường hợp này hoạt động chính xác theo VS2008. Sự khác biệt chính là theo VS2010, toàn bộ ứng dụng được biên dịch cho .NET 4 và dưới VS2008, biên dịch sang .NET 2. Cả hai đều chạy 64 bit.
Cập nhật 7:
Giống như đã đề cập, tôi có mdbg chạy dưới 64-bit. Thật không may, nó cũng có vấn đề về điểm dừng khi nó không bị hỏng nếu tôi chạy lại chương trình (điều này ngụ ý rằng nó được biên dịch lại, do đó không sử dụng cùng một cụm, nhưng vẫn sử dụng cùng một nguồn).
Cập nhật 8:
Tôi đã gửi một lỗi tại trang web MS Connect liên quan đến vấn đề điểm dừng.
Cập nhật: Đã sửa
Cập nhật 9:
Sau một thời gian dài suy nghĩ, cách duy nhất để làm cho trình gỡ lỗi hài lòng dường như là thực hiện SSA, vì vậy mọi bước có thể được tách biệt và tuần tự. Tôi vẫn chưa chứng minh khái niệm này mặc dù. Nhưng nó có vẻ hợp lý. Rõ ràng, việc dọn dẹp temps từ SSA sẽ phá vỡ việc gỡ lỗi, nhưng điều đó rất dễ để chuyển đổi và khiến chúng không có nhiều chi phí.
nop
s, bước không thành công (tôi sẽ xác minh lại điều này một lần nữa để chắc chắn). Đó là một sự hy sinh tôi đoán tôi sẽ phải thực hiện. Nó không giống như VS thậm chí có thể chạy mà không có quyền quản trị viên :) Btw sử dụng Reflection.Emit thông qua DLR (một nhánh rất sớm bị hack).