Tôi có thể tìm ra giá trị trả về trước khi quay lại trong khi gỡ lỗi trong Visual Studio không?


387

Thực hiện chức năng sau:

DataTable go() {
    return someTableAdapter.getSomeData();
}

Khi tôi đặt điểm dừng trong chức năng này, có khả năng kiểm tra giá trị được trả về không? go()được ghép trực tiếp vào một datagrid trong một .aspxtrang.

Cách duy nhất để kiểm tra dữ liệu được trả về là sử dụng một biến tạm thời. Tuy nhiên, đó là một chút bất tiện. Có cách nào khác không?


1
Bạn có thể thêm đồng hồ nếu bạn di chuyển ngược lên ngăn xếp cuộc gọi
Chris S

Bạn đã từng có thể làm điều này trong VB6, tôi dường như nhớ. Nhưng trước đó, cú pháp cho các hàm liên quan đến việc đặt giá trị của hàm thành giá trị trả về ...
Neil Barnwell

5
Nhận xét cho người dùng Visual C ++: Nhập $ ReturnValue trong Cửa sổ ngay lập tức hoặc Cửa sổ xem. Ít nhất trên VS 2010 của tôi nó đã hoạt động!
sergiol

9
Đối với VS2015, hãy sử dụng $ ReturnValue1 .. trong trường hợp bạn không muốn đọc qua 20 câu trả lời và 100 bình luận bên dưới!
felickz

3
Câu trả lời năm 2019 cho tất cả những điều này là gì? Những câu trả lời là siêu ngày.
dylanh724

Câu trả lời:


264

Không phải là tôi biết. Lưu ý rằng nếu bạn làm thêm một biến, nó sẽ bị xóa bỏ bởi trình biên dịch trong phiên bản xây dựng anyway ...

Cập nhật: Chức năng này đã được thêm vào VS2013 . Bạn có thể thấy các giá trị trả về trong các cửa sổ tự động hoặc sử dụng $ReturnValuetrong cửa sổ đồng hồ / ngay lập tức.

Giá trị chỉ có thể được nhìn thấy trực tiếp sau khi trở về từ hàm, do đó cách dễ nhất để truy cập là bằng cách đặt một điểm dừng trên lệnh gọi hàm và bước qua (F10) cuộc gọi.


Cập nhật cho VS2015: boo! thật không may, nó không xuất hiện trong bản
cập nhật VS2015 (devenv v14) cho VS2017: nó đã trở lại. (devenv v15)


12
Lý do để từ bỏ temp là khả năng đọc & phong cách, không hiệu quả, không?
orip

8
Có thể kể từ khi VS 2010 với IntelliTrace: blogs.msdn.com/b/habibh/archive/2009/10/23/...
Daniel Hilgarth

2
Intellitrace chỉ có sẵn trong phiên bản VS Ultimate.
JMGH

3
@MarcGravell Câu trả lời của bạn là sai ! Chắc chắn, tôi đã mất sáu năm giữa trả lời của bạn và MS phát hành tính năng đó trong VS13, nhưng vẫn còn. Nếu bạn chỉ thêm " trong thời gian hiện tại " như một sự từ chối ... (Không, tôi không bị chậm phát triển. Đó một trò đùa, tất nhiên. Bạn thật đáng mến, bạn đời.)
Konrad Viltersten

6
@MarcGravell cho VS2015: $ ReturnValue1 hoạt động! (đã thử nghiệm trong phiên bản cuối cùng)
GY

58

Điều này có thể được thực hiện trong Visual Studio 2013 với CLR 4.5.1 theo trang web phản hồi của khách hàng . Nó không có sẵn trong các phiên bản trước cho C #.

(Visual Studio 2008 và trước đó đã hỗ trợ nó cho VB.NET. Nó luôn có sẵn cho các nhà phát triển C / C ++.)


1
Làm thế nào để bạn làm điều này trong Visual Studio 2010 C ++?
Người dùng

Microsoft Connect cho biết có một vấn đề cơ bản với mã được quản lý ngăn chặn việc thực hiện điều này một cách đáng tin cậy:
Dan Solovay

@DanSolovay Những từ họ sử dụng là "chúng tôi không thể làm điều đúng đắn" (đối với VS11) nhưng họ "muốn mang điều này trở lại" và "đang xem xét một số giải pháp tiềm năng cho vấn đề này".
Alex Angas

Các mục kết nối đã cũ. Tính năng này dường như bị ... bỏ rơi: (((
Softlion

1
Có thể kể từ khi VS 2010 với IntelliTrace: blogs.msdn.com/b/habibh/archive/2009/10/23/...
Daniel Hilgarth

25

Tôi đồng ý rằng đây là một điều rất hữu ích: không chỉ thấy giá trị trả về của phương thức trước khi bước ra khỏi nó, mà còn thấy giá trị trả về của các phương thức tôi vừa bước qua. Tôi đã triển khai nó như một phần của một phần mở rộng thương mại cho Visual Studio có tên là " OzCode ".

Với nó, bạn có thể xem các giá trị trả về của phương thức ngay trên trình soạn thảo mã, dưới dạng hiển thị HUD:

Tuyên bố trực quan

Để biết thêm thông tin, xin vui lòng xem video này .


23

Theo Microsoft, không có cách nào để thực hiện điều này một cách đáng tin cậy với mã được quản lý. Đây là một vấn đề họ nhận thức được và đang giải quyết:

Đối với những người có kinh nghiệm gỡ lỗi mã C ++ hoặc VB6 bản địa, bạn có thể đã sử dụng một tính năng trong đó các giá trị trả về hàm được cung cấp cho bạn trong cửa sổ Ô tô. Thật không may, chức năng này không tồn tại cho mã được quản lý. Mặc dù bạn có thể giải quyết vấn đề này bằng cách gán các giá trị trả về cho một biến cục bộ, nhưng điều này không thuận tiện vì nó yêu cầu sửa đổi mã của bạn. Trong mã được quản lý, sẽ khó hơn rất nhiều để xác định giá trị trả về của hàm bạn đã thực hiện. Chúng tôi nhận ra rằng chúng tôi không thể thực hiện đúng mọi thứ ở đây và vì vậy chúng tôi đã xóa tính năng này thay vì cung cấp cho bạn kết quả không chính xác trong trình gỡ lỗi. Tuy nhiên, chúng tôi muốn mang lại điều này cho bạn và các nhóm CLR và Debugger của chúng tôi đang xem xét một số giải pháp tiềm năng cho vấn đề này. Thật không may, đây không phải là một phần của Visual Studio 11.

https://connect.microsoft.com/VisualStudio/feedback/details/597933/add-a-return-pseudo-variable-to-the-visual-studio-debugger-for-net-code


1
Per @Alex ở trên ( stackoverflow.com/a/3714884/402949 ), điều này có sẵn cho VS2013 với CLR 4.5
Dan Solovay

21

Về Visual Studio 2015:

Theo câu trả lời hiện đang được chấp nhận bởi Marc Gravell:

Đây chức năng đã được thêm vào Visual Studio 2013 . Bạn có thể thấy các giá trị trả về trong các cửa sổ tự động hoặc sử dụng $ ReturnValue trong cửa sổ đồng hồ / ngay lập tức

Câu trả lời đó cũng nói rằng chức năng này không hoạt động trong Visual Studio 2015. Điều này không hoàn toàn đúng. Trên Kiểm tra giá trị trả về của các cuộc gọi phương thức, có lưu ý sau:

Bạn phải bật các trình đánh giá biểu thức kế thừa để $ ReturnValue được công nhận (Công cụ / Tùy chọn / Gỡ lỗi / Sử dụng các trình đánh giá biểu thức C # và VB kế thừa ). Nếu không, bạn có thể sử dụng $ ReturnValue1 .

Tôi đã thử nghiệm điều này trong Visual Studio 2015 Enterprise:

  • Với các trình đánh giá biểu thức kế thừa đã tắt: chỉ $ ReturnValue1 hoạt động
  • Với các trình đánh giá biểu thức kế thừa được bật: cả $ ReturnValue $ ReturnValue1 đều hoạt động

3
Điều này không còn cần thiết nữa. Trên VS 2015 Update 3, tôi đã vô hiệu hóa các đánh giá kế thừa và $ReturnValuehoạt động. Tuy nhiên, giá trị trả về sẽ không xuất hiện ở bất cứ đâu nếu bạn Use managed compatibility modebật tùy chọn gỡ lỗi.
Nick

13

Nếu bạn vào menu Công cụTùy chọn , IntelliTrace và thay đổi cài đặt để thu thập sự kiện và thông tin cuộc gọi.

Bạn có thể quay lại sự kiện cuộc gọi trước đó ( Ctrl+ Shift+F11 ) và xem giá trị tạm thời được trả về từ cuộc gọi phương thức trong cửa sổ tự động dưới dạng con của tên phương thức.

Điều này không hiển thị cho bạn giá trị trả về cho phương thức bạn đang tham gia. Nó chỉ hiển thị cho bạn giá trị trả về của phương thức cuối cùng được gọi trong phương thức hiện tại.

Vì vậy, nó tốt cho

DataTable go(){return someTableAdapter.getSomeData();}

vì nó cho bạn thấy giá trị trả về cho someTableAdapter.getSomeData().

Nhưng không phải cho:

int go(){return 100 * 99;}

12

Thủ thuật cũ từ những ngày .NET trước: Mở cửa sổ Đăng ký và xem giá trị của thanh ghi EAX. Điều này chứa giá trị trả về của hàm cuối cùng được gọi.


1
+1 cho trường học cũ gần hơn với phương pháp kim loại - tuy nhiên, điều này sẽ không hoạt động đối với tất cả các giá trị trả về (và rõ ràng là tùy thuộc vào JIT'er - ai biết tối ưu hóa điên rồ nào mà nó có thể quyết định sẽ không sử dụng EAX? ). Đối với các loại tích phân, nó sẽ (chủ yếu?) Hoạt động. Các loại giá trị lớn là một vấn đề khác (và theo như tôi nhớ từ một số bài đăng trên blog, những loại này sẽ không được hiển thị trong VS2013).
JimmiTh

10

Bước ra khỏi phương thức go () bằng Shift-F11, và sau đó trong cửa sổ gỡ lỗi "Ô tô", nó sẽ hiển thị giá trị trả về của lệnh gọi phương thức vừa bật ra khỏi ngăn xếp (trong trường hợp này là phương thức go () bạn muốn gì). Đây là hành vi trong Visual Studio 2005; Tôi chưa sử dụng Visual Studio 2008 vì vậy tôi không biết liệu điều này có hoạt động giống như vậy trong phiên bản đó không.


Tôi đã thử điều này trong cả VS2005 và VS2008, nhưng tôi không thực sự thấy nó. Tôi có cửa sổ "Ô tô" mở, nhưng khi ở chức năng "đi", cửa sổ ô tô chỉ trống. Ngoài ra khi bước ra khỏi chức năng (dấu ngoặc nhọn đóng của hàm có màu vàng). Bạn có thể cho tôi thêm một gợi ý?
doekman

Tôi hy vọng cửa sổ Tự động sẽ trống trong khi NỘI DUNG hàm go (). Bạn cần bước HOÀN TOÀN hàm của hàm (tức là con trỏ gỡ lỗi sẽ trỏ đến hàm đã GỌI go ()) và sau đó bạn sẽ thấy giá trị trả về cho go () trong cửa sổ Ô tô.
LeopardSkinPillBoxHat

@LeopardSkinPillBoxHat: không thể làm việc này, ngay cả với gợi ý thêm của bạn. Bạn đang thử điều này trong Visual Basic? Nó dường như có sự hỗ trợ tốt hơn để quan sát và thay đổi giá trị trả về ...
Roman Starkov

@romkyns - Điều gì hiển thị trong cửa sổ "Ô tô" cho bạn? Nó không hiển thị một dòng cho biết chức năng được gọi cuối cùng trả về là gì?
LeopardSkinPillBoxHat

2
@LeopardSkinPillBoxHat: không, nó không làm điều đó trong C #. PS Wow, tôi đã mất một lúc để thấy điều này một lần nữa.
Roman Starkov

7

Vâng, có một cách rất hay. Một nhược điểm đáng kể là bạn phải chờ 5, có thể 6 năm. Vì tôi thấy rằng bạn đã đăng vào tháng 11 năm 2008, tôi đề nghị bạn nên chờ đợi ...

... aaaait. Và Voila! Chỉ dành cho bạn, MS đã phát hành Visual Studio 2013 mới nhất với tính năng mặc định có thể truy cập từ các menu trong khi chạy ở chế độ gỡ lỗi (menu DebugWindowsAutos ).


@Doug Vì câu hỏi đã được hỏi vào tháng 11 năm 2008 và câu trả lời của tôi được đưa ra vào tháng 9 năm 2014. Người đăng ban đầu có thể hài lòng và không muốn chuyển tín dụng. Nhưng tôi đồng ý với bạn - tôi sẽ không bận tâm thêm một vài câu trả lời nữa. Tôi thích upies và rep đạt được. :)
Konrad Viltersten

Có vấn đề này ngày hôm nay. Cảm ơn bạn đã trả lời vào năm 2014 mặc dù vấn đề ban đầu là của năm 2008. Câu trả lời của bạn là điều tôi đang tìm kiếm.
AP

@AP Không có vấn đề. Cảm thấy giống như một cỗ máy thời gian để xem bài đăng này. Vụ nổ từ quá khứ, hehe.
Konrad Viltersten

5

Có rất nhiều cách giải quyết, nhưng không có gì có vẻ thỏa đáng.

Để trích dẫn John Skeet bên dưới (nhận xét về câu trả lời hiện đã bị xóa):

Vẫn có vẻ bất tiện đối với tôi - đặc biệt là nếu bạn không biết giá trị trả về nào bạn sẽ cần trước khi bắt đầu gỡ lỗi. Tôi thực sự không muốn phải có một biến tạm thời làm lộn xộn mã của tôi mỗi khi tôi trả lại bất cứ thứ gì.

Về lý thuyết, trình gỡ lỗi có thể có returnkhả năng thay đổi. Xét cho cùng: đó chỉ là một biến trên ngăn xếp:

unsafe {
  int * sp = stackalloc int[1];
  try {
    return a+b;
  }
  finally {
    Trace.WriteLine("return is " + *(sp+3));
  }
}

Vì vậy, hãy coi đây là một yêu cầu tính năng cho Visual Studio.


có một sự khác biệt khá lớn giữa một biến (một địa phương được xác định rõ) và một giá trị trên ngăn xếp. Đó là một giá trị trên ngăn xếp, nhưng nó không phải là một biến (= local).
Marc Gravell

@Marc: Tôi không chắc CLR hoạt động như thế nào, nhưng rất nhiều trình biên dịch đặt các đối số hàm lên ngăn xếp bên dưới con trỏ ngăn xếp (sp) và các biến cục bộ trên ngăn xếp, phía trên con trỏ ngăn xếp. Đó chỉ là những gì tôi đang cố gắng thể hiện. Và OK, khi giá trị trả về là loại tham chiếu, bạn chỉ cần lấy một số giá trị con trỏ.
doekman

1
Nó không nhất thiết phải trên ngăn xếp. Thực tế, nếu bạn xem Debug -> Người đăng ký bạn có thể thấy nó trong EAX
Mark Sowul

5

Tôi muốn mở rộng dựa trên câu trả lời của PascalK để làm cho điều này hoạt động trong Visual Studio 2015, bởi vì có một tính năng ẩn không được ghi lại trong Kiểm tra giá trị trả về của các lệnh gọi phương thức .

Nếu bạn có các lệnh gọi hàm lồng nhau, các biến giả $ResultValueXsẽ được tạo tự động, trong đó X đề cập đến thứ tự gọi hàm. Vì vậy, nếu bạn có một cuộc gọi như Multiply(Five(), Six()), các biến giả sau đây được tạo:

Five()     | $ResultValue1 = 5
Six()      | $ResultValue2 = 6
Multiply() | $ResultValue3 = 30

2

Microsoft Visual C ++ đã từng làm điều này, nhưng Visual Studio không AFAIK .. :(


2

Cách duy nhất tôi biết là đặt một điểm dừng trên dòng trả về và sau đó gọi cửa sổ Xem nhanh và nhập biểu thức được trả về:

someTableAdapter.getSomeData();

Nhưng điều này chỉ hoạt động nếu cuộc gọi không thay đổi trạng thái của bất kỳ đối tượng nào (vì sẽ có cuộc gọi thứ hai đến cùng phương thức khi bạn sẽ tiếp tục thực hiện).


5
Điều này cũng chỉ hoạt động nếu biểu hiện của bạn không có lambdas.
Roman Starkov

1

Bạn cũng có thể yêu cầu đánh giá giá trị trong cửa sổ trung gian, nếu nó không đặt cờ hoặc các biến khác, mà chỉ trả về một cái gì đó.


Bạn cần bao gồm lambda trong câu hỏi, vì đôi khi tôi cũng sử dụng cửa sổ ngay lập tức
Chris S

1

Tôi nghĩ bạn có thể xác định điều này bằng cách xem thanh ghi RAX trong cửa sổ Thanh ghi (Gỡ lỗi / Windows / Đăng ký). Sau khi bước ra (SHIFT + F11) của chức năng, hãy kiểm tra thanh ghi RAX. Tôi không biết thực tế, nhưng một lần trên mặt trăng, bạn có thể kiểm tra một thanh ghi (ngày .NET trước) và xem giá trị trả về ở đó. Nó thậm chí có thể là sự kết hợp của RAX và RBX, v.v.


1

Mở cửa sổ Gỡ lỗi → Ô tô sẽ giúp bạn đóng. Nó sẽ không hiển thị giá trị hoàn trả thực tế, nhưng nó sẽ hiển thị những gì được đánh giá trong tuyên bố hoàn trả.


2
Không thể có cửa sổ ô tô VS2008 để hiển thị bất cứ thứ gì như vậy. Ông có thể làm rõ?
Roman Starkov

return x + y; Ý tôi là nếu bạn đặt điểm dừng trên dòng này, thì cửa sổ Debug-Autos của bạn sẽ hiển thị các giá trị hiện tại cho x và y. Như tôi đã nói, nó chỉ khiến bạn gần gũi. Chỉ cần cố gắng để giúp đỡ. Tôi không nghĩ rằng nó xứng đáng với một downvote.
GeekyMonkey

1

Vâng, bằng cách chuyển sang VB.NET. ; P (Bạn đã chỉ nói "Visual Studio" .;)

Miễn là tôi có thể nhớ (từ Visual Basic qua tất cả các phiên bản VB.NET), bạn chỉ cần truy vấn tên hàm. Nó "hàm" giống như một biến cục bộ được khai báo ngầm khi bắt đầu hàm và giá trị hiện tại của nó cũng được sử dụng làm giá trị trả về bất cứ khi nào hàm thoát qua câu lệnh không trả về nghĩa là (tất nhiên Exit Functionhoặc chỉ rơi qua) và dĩ nhiên, khi câu lệnh return được sử dụng.

Nó cũng được đặt thành biểu thức của câu lệnh return. Giống như một biến cục bộ, giá trị của nó có thể được kiểm tra tại bất kỳ điểm thực thi nào bên trong hàm (bao gồm cả sau khi câu lệnh return được thực thi). C # không có cái này và nên.

Tính năng VB.NET nhỏ bé đó (cộng với Exit Functioncâu lệnh mà nó kích hoạt - một tính năng khác C # không có và nên) rất hữu ích trong một hình thức lập trình phòng thủ mà tôi thực hành khi tôi luôn khởi tạo tên hàm thành giá trị thất bại / mặc định là tuyên bố đầu tiên. Sau đó, tại bất kỳ điểm thất bại nào (thường xảy ra thường xuyên hơn nhiều so với điểm thành công), tôi chỉ có thể gọi Exit Functioncâu lệnh (nghĩa là không phải lặp lại biểu thức fail / default hoặc thậm chí là tên hằng / biến).


1

Câu trả lời được chấp nhận không hoạt động đúng với Visual Studio 2015, nhưng bằng cách đặt một điểm dừng trên dòng cuối cùng của phương thức và nhấn F10, nó sẽ đặt tất cả các biểu thức của giá trị trả về vào cửa sổ cục bộ.


Bạn có thể cũng có thể chỉnh sửa câu trả lời được chấp nhận để bao gồm ý kiến ​​của bạn.
doekman

0

Bạn có thể thử chọn "someTableAdapter.getSomeData();", nhấp chuột phải vào nó và xem Quick Watch .


-1

Kéo và thả biểu thức trả về vào cửa sổ xem.

Ví dụ, trong tuyên bố

return someTableAdapter.getSomeData();

kéo và thả

someTableAdapter.getSomeData()

vào một cửa sổ xem và bạn sẽ thấy giá trị.

Bạn có thể làm điều này cho bất kỳ biểu thức.


2
Vấn đề với điều đó: biểu thức được đánh giá hai lần.
doekman

6
Và biểu thức đồng hồ không thể chứa biểu thức lambda, mà tôi sử dụng một chút công bằng.
Steve Crane
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.