Чи можу я дізнатися значення повернення перед поверненням під час налагодження у Visual Studio?


387

Виконайте таку функцію:

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

Коли я встановлюю точку розриву в цій функції, чи є можливість перевірити повернене значення? go()безпосередньо пов'язаний з мережею даних на .aspxсторінці.

Єдиний спосіб перевірити повернуту таблицю даних - це використовувати тимчасову змінну. Однак це трохи незручно. Хіба немає іншого способу?


1
Ви можете додати годинник, якщо перенести резервну копію стека викликів
Chris S

Ви раніше могли це робити в VB6, я, мабуть, пам’ятаю. Але тоді синтаксис функцій, що стосуються встановлення значення функції на повернене значення ...
Ніл Барнвелл,

5
Коментар для користувачів Visual C ++: Введіть $ ReturnValue у негайне вікно або у вікно перегляду. Принаймні, на моєму VS 2010 це працювало!
sergiol

9
Для VS2015 використовуйте $ ReturnValue1 .. якщо ви не хочете прочитати 20 відповідей та 100 коментарів нижче!
felickz

3
Яка відповідь на все це у 2019 році? Ці відповіді датовані супер.
dylanh724

Відповіді:


264

Не те, що я знаю. Зверніть увагу , що якщо ви робите додати змінний, вона віддаляється компілятором у звільненні будує все одно ...

Оновлення: ця функція додана до VS2013 . Ви можете бачити повернені значення у вікнах автомашини або використовувати їх $ReturnValueу вікні годинника / безпосереднього доступу.

Значення можна побачити лише після повернення з функції, таким чином, найпростіший спосіб отримати доступ до нього - встановивши точку розриву на виклик функції та переступивши (F10) виклик.


Оновлення для VS2015: boo! на жаль, схоже, це не є у VS2015 (devenv v14)
Оновлення для VS2017: воно повернулося. (devenv v15)


12
Причиною відмови від темпу є читабельність та стиль, а не ефективність, ні?
orip

8
Це можливо з VS 2010 з IntelliTrace
Daniel Hilgarth

2
Intellitrace просто доступний у VS Ultimate Edition.
JMGH

3
@MarcGravell Ваша відповідь неправильна ! Звичайно, мені знадобилося шість років між вашою відповіддю та MS, що випускає цю функцію в VS13, але все ж. Якби ти лише доки додав " поки що " як відмову від відповідальності ... (Ні, я не відстала. Звичайно , це жарт. Ти богоподібний, товариш.)
Конрад Вільтерстен,

6
@MarcGravell для VS2015: $ ReturnValue1 працює! (перевірено в кінцевій версії)
GY

58

Це можна зробити у Visual Studio 2013 за допомогою CLR 4.5.1 відповідно до сайту відгуків клієнтів . Він не був доступний у попередніх версіях для C #.

(Visual Studio 2008 і раніше підтримували його для VB.NET. Він завжди був доступний розробникам C / C ++.)


1
Як це зробити у Visual Studio 2010 C ++?
Користувач

Microsoft Connect каже, що існує принципова проблема керованого коду, який заважає реалізувати це надійно:
Дан Соловай

@DanSolovay Слова, які вони використовують, - "ми не могли зробити правильно все послідовно" (для VS11), але вони "хочуть повернути це" і "шукають ряд можливих рішень цієї проблеми".
Алекс Ангас

Запис підключення несвіжий. Здається, функція ... занедбана: (((
Softlion

1
Це можливо з VS 2010 з IntelliTrace
Daniel Hilgarth

25

Я погоджуюся, що це дуже корисна річ: не тільки бачити повернене значення методу перед тим, як вийти з нього, але і бачити повернене значення методів, які я щойно переступив. Я реалізував це як частину комерційного розширення до Visual Studio під назвою " OzCode ".

З його допомогою ви можете переглядати значення повернення методу прямо в редакторі коду як різновид HUD-дисплея:

Візуалізація заяви

Для отримання додаткової інформації дивіться це відео .


23

На думку Microsoft, немає можливості надійно реалізувати це за допомогою керованого коду. Це проблема, яку вони знають і над якою працюють:

Для тих, хто там має досвід налагодження нативного C ++ або VB6 коду, можливо, ви використали функцію, коли значення повернення функцій надаються вам у вікні Автозавантаження. На жаль, ця функціональність не існує для керованого коду. Хоча ви можете вирішити цю проблему, призначивши значення повернення локальній змінній, це не так зручно, оскільки вимагає змінити ваш код. В керованому коді набагато складніше визначити, яке повернене значення функції ви перейшли. Ми зрозуміли, що тут не можемо робити все правильно, і тому ми видалили функцію, а не дали невірні результати у відладці. Однак ми хочемо повернути це для вас, і наші команди CLR та налагоджувача розглядають ряд потенційних рішень цієї проблеми. На жаль, це не буде частиною 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
За @Alex вище ( stackoverflow.com/a/3714884/402949 ), це є для VS2013 з CLR 4.5
Dan Соловея

21

Щодо Visual Studio 2015:

Відповідно до прийнятої на даний момент відповіді Марка Гравелла:

Ця функціональність додана до Visual Studio 2013 . Ви можете бачити повернені значення у вікнах автомашин або використовувати $ ReturnValue у вікні годинника / негайного перегляду

У цій відповіді також зазначено, що ця функціональність не працює в Visual Studio 2015. Це не (цілком) вірно. Про Вивчення зворотних значень викликів методу є така примітка:

Ви повинні мати в спадщині вираз оцінювачів включаються на $ ReturnValue бути визнаними (Tools / Options / Налагодження / Використовуйте старі C # і VB вираження оцінювачів ). В іншому випадку ви можете використовувати $ ReturnValue1 .

Я перевірив це в Visual Studio 2015 Enterprise:

  • При відключеному застарілому оцінці виразів: працює лише $ ReturnValue1
  • Увімкнено оцінювачі застарілих виразів: і $ ReturnValue, і $ ReturnValue1 працюють

3
Це більше не видається необхідним. У версії VS 2015 Update 3 у мене відключені оцінювачі застарілих і $ReturnValueпрацюють. Однак повернене значення ніде не з’являється, якщо у вас Use managed compatibility modeвключена опція налагодження.
Нік

13

Якщо ви перейдете до меню ІнструментиПараметри , IntelliTrace та змініть налаштування для збору подій та інформації про дзвінки.

Ви можете повернутися до попередньої події виклику ( Ctrl+ Shift+F11 ) і побачити тимчасове значення, повернене з виклику методу, у вікні авто як дочірнє ім'я методу.

Це не показує вам повернене значення для методу, в якому ви перебуваєте. Він просто показує повернене значення останнього методу, викликаного в поточному методі.

Отже, це добре для

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

як це показує вам повернене значення someTableAdapter.getSomeData() .

Але не для:

int go(){return 100 * 99;}

12

Старий трюк з попередніх .NET днів: відкрийте вікно регістрів і подивіться на значення регістра EAX. Це містить повернене значення останньої викликаної функції.


1
+1 для старої школи, ближче до металевого підходу - це, однак, не спрацює з усіма поверненими значеннями (і, очевидно, це залежить від JIT'er - хто знає, яка шалена оптимізація може вирішити, що не використовуватиме EAX? ). Для цілісних типів це буде працювати (в основному?). Великі типи значень - це інша справа (і наскільки я пам’ятаю з деяких публікацій в блозі, вони також не відображатимуться у VS2013).
JimmiTh

10

Вийдіть із методу go (), використовуючи Shift-F11, а потім у вікні налагодження "Автомати" відобразиться значення повернення виклику методу, який щойно вискочив з стека (у цьому випадку методу go (), який є що ти хочеш). Така поведінка у Visual Studio 2005; Я не використовував Visual Studio 2008, тому не знаю, чи так поводиться в цій версії.


Я пробував це як у VS2005, так і в VS2008, але насправді цього не бачу. У мене відкрите вікно "Автоматизація", але коли у функції "йти", автоматичне вікно просто порожнє. Також при виході з функції (закриваюча фігурна дужка функції жовта). Чи можете ви дати мені ще одну підказку?
doekman

Я б очікував, що вікно Автоматики буде порожнім під час ВНІСНЕННЯ функції go (). Потрібно виконувати функцію ПОПЕРЕДЖЕННЯ функції (тобто курсор налагодження повинен вказувати на функцію, яка має CALLED go ()), а потім у вікні Autos слід побачити значення повернення для go ().
LeopardSkinPillBoxHat

@LeopardSkinPillBoxHat: не вдається змусити це працювати, навіть із вашим додатковим підказом. Ви пробуєте це в Visual Basic? Схоже, є краща підтримка для спостереження та зміни повернених значень ...
Роман Старков

@romkyns - Що відображається у вікні "Автомобілі" для вас? Чи не відображається рядок із зазначенням того, що повернулася остання викликана функція?
LeopardSkinPillBoxHat

2
@LeopardSkinPillBoxHat: ні, це не робиться в C #. PS Вау, знадобилося мені трохи часу, щоб побачити це знову.
Роман Старков

7

Так, є дуже приємний спосіб. Важливим недоліком є ​​те, що вам доведеться чекати 5, можливо, 6 років. Оскільки я бачу, що ви опублікували в листопаді 2008 року, я пропоную вам waaaaaa ...

... ааааіт. І вуаля! Тільки для вас MS випустила останню Visual Studio 2013, де це функція за замовчуванням, доступна з меню під час роботи в режимі налагодження (меню НалагодженняWindowsАвто ).


@Doug Оскільки запитання було задано в листопаді 2008 року, а моя відповідь надійшла у вересні 2014 року. Оригінальний плакат, ймовірно, задоволений і не хоче переміщувати кредит. Але я згоден з вами - я не заперечував би ще декількома перевагами щодо своєї відповіді. Мені подобаються підвищення та репліка. :)
Konrad Viltersten

Це питання було сьогодні. Дякуємо, що відповіли у 2014 році, хоча початковий випуск був у 2008 році. Ваша відповідь - це те, що я шукав.
AP

@AP Немає проблем. Відчуває себе трохи, як машина часу, щоб побачити цю публікацію. Вибух з минулого, хе-хе.
Конрад Вільтерстен

5

Існує багато рішень, але жодне не здається задовільним.

Щоб цитувати Джона Скіта нижче (коментуйте видалену відповідь):

Все ще виглядає незручно для мене - особливо якщо ви не знаєте, яке повернене значення вам знадобиться, перш ніж почати налагодження. Я дійсно не хочу мати тимчасову змінну, що захаращує мій код кожен раз, коли я повертаю що-небудь

Теоретично налагоджувач може мати return-змінний. Зрештою: це просто змінна в стеці:

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

Тож вважайте це запитом функції для Visual Studio.


Існує досить велика різниця між змінною (чітко визначена локальна) і значенням на стеку. Це значення в стеку, але це не змінна (= local).
Marc Gravell

@Marc: Я не впевнений, як працює CLR, але багато компіляторів ставлять аргументи функції на стеку нижче вказівника стека (sp) та локальних змінних на стеці над вказівником стека. Це саме те, що я намагаюся показати. І нормально, коли значення, що повертається, є еталонним типом, ви просто отримуєте деяке значення вказівника.
doekman

1
Це не обов'язково на стеці. Насправді, якщо ви переглядаєте налагодження -> регістри, ви готові бачити це в EAX
Марк Совул

5

Я хотів розкрити відповідь Паскальк про те, щоб змусити це працювати в Visual Studio 2015, тому що є прихована функція, яка не зафіксована в Розгляненні повернених значень викликів методів .

Якщо ви вклали виклики функцій, псевдо-змінні $ResultValueXавтоматично створюються, де X посилається на порядок виклику функції. Отже, якщо у вас є такий виклик, як Multiply(Five(), Six()), створюються такі псевдо-змінні:

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

2

Microsoft Visual C ++ використовував для цього, але Visual Studio не робить AFAIK .. :(


2

Єдиний спосіб мене знає - розмістити точку перерви на лінії повернення, а потім зателефонувати у вікно швидкого перегляду та ввести повернене вираз:

someTableAdapter.getSomeData();

Але це працює лише в тому випадку, якщо виклик не змінить стан будь-якого об'єкта (оскільки після повторного виконання буде другий виклик того ж методу).


5
Це також працює, лише якщо у вашому вираженні немає лямбда.
Роман Старков

1

Ви також можете попросити оцінити значення і в проміжному вікні, якщо воно не встановлює прапори чи інші змінні, а лише повертає щось.


Вам потрібно включити лямбда у запитання, оскільки я іноді використовую безпосереднє вікно
Chris S

1

Я думаю, ви можете це визначити, подивившись на регістр RAX у вікні регістрів (налагодження / Windows / регістри). Після виходу (SHIFT + F11) функції перевірте регістр RAX. Я не знаю фактично, але одного разу на місяці ви могли перевірити реєстр (до .NET днів) і побачити там повернене значення. Це може бути навіть комбінація RAX та RBX тощо.


1

Відкриття вікна налагодження → Автоматизація закриває вас. Він не відображатиме фактичне значення повернення, але покаже, що було оцінено у виписці з повернення.


2
Не вдалося отримати вікно автоматичного VS2008, щоб показати щось подібне. Не могли б ви уточнити?
Роман Старков

return x + y; Що я мав на увазі, якщо ви встановите точку розриву на цій лінії, то у вашому вікні Debug-Autos відображаться поточні значення для x та y. Як я вже говорив, це ви тільки закриєте. Просто намагаюся бути корисним. Я не вважаю, що це заслуговує уваги.
GeekyMonkey

1

Так, перейшовши на VB.NET. ; P (Ви щойно сказали "Visual Studio";;)

Поки я пам'ятаю (від Visual Basic через усі версії VB.NET), ви можете просто запитати ім'я функції. Він "функціонує" як локальна змінна, яка неявно оголошується на початку функції, і її поточне значення також використовується як повернене значення кожного разу, коли функція виходить за допомогою засобу non-return оператора (тобтоExit Function або просто пропадає) і, звичайно, коли використовується повернення заяви.

Він також встановлений на вираз повернення. Як і локальна змінна, її значення можна перевірити в будь-якій точці виконання всередині функції (в тому числі після виконання оператора return). У C # цього немає і слід.

Ця маленька функція VB.NET (плюс Exit Functionзаява, яку вона дозволяє - інша функція C # не має і не повинна) дуже корисна у формі оборонного програмування, яке я практикую, коли я завжди ініціалізую ім'я функції до значення відмов / за замовчуванням як перше твердження. Тоді в будь-якій точці відмови (яка зазвичай трапляється набагато частіше, ніж точки успіху), я можу просто зателефонувати у Exit Functionвисловлювання (тобто, не дублюючи вираз відмови / за замовчуванням або навіть ім'я постійної / змінної).


1

Прийнята відповідь не працює належним чином для Visual Studio 2015, але, поставивши крапку в останньому рядку методу та натиснувши F10, вона помістить усі вирази повернутого значення у вікно локальних жителів.


Ви також можете редагувати прийняту відповідь, щоб включити свої коментарі.
doekman

0

Ви можете спробувати вибрати "someTableAdapter.getSomeData();", клацніть правою кнопкою миші та перейти до швидкого перегляду .


-1

Перетягніть зворотний вираз у вікно перегляду.

Наприклад, у заяві

return someTableAdapter.getSomeData();

перетягни та Впусти

someTableAdapter.getSomeData()

у вікно годинника, і ви побачите цінність.

Це можна зробити для будь-якого виразу.


2
Проблема з цим: вираз оцінюється двічі.
doekman

6
І вирази годин не можуть містити лямбда-виразів, які я досить часто використовую.
Стів Крейн
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.