Отладка в Visual Studio

Значение отладчика в работе программиста трудно переоценить. Как бы вы хорошо не писали код, как бы не была хороша ваша команда, но даже если ваш проект имеет всего несколько тысяч строк кода, написанных двумя разработчиками, то вы не можете гарантировать отсутствие ошибок. Да, современные IDE, в частности, Visual Studio, позволяют избегать множества ошибок уже на этапе написания кода, но, как минимум, вы можете упустить какие-то моменты, из-за которых ваше приложение работает не так быстро, как хотелось бы, или ошибка возникает при каких-то граничных условиях, которые не были рассмотрены ранее. Разобраться в причинах не корректной работы помогает отладчик.

Отладчик Visual Studio, на мой взгляд, самый удобный и мощный среди всех IDE написанный на текущий момент. Даже если мы рассматриваем не только среду .NET.

Конечно, существуют более специализированные вещи, представляющие из себя гораздо более мощные инструменты. Можете обратить внимание на диаграмму:

Размер бороды программиста в зависимости от используемого отладчика

Изображение взято из статьи отсюда: https://habrahabr.ru/company/jugru/blog/326454/ (в статье вы можете узнать больше про WinDbg)

Но отладчик Visual Studio достаточно универсальный, он может помочь, наверное, с поиском 98% возникающих проблем в проектах. Но проблема в том, что очень много разработчиков не использует все возможности отладчика. Даже когда мы говорим об опытных программистах, которые работают много лет и успешно пишут код, не используют множество доступного функционала, который может здорово упростить жизнь и сэкономить время. Многие скажут, что это и не нужно, код можно писать и в блокноте, а во время отладки достаточно узнать какое значение приходит, получить код ошибки и, возможно, увидеть несколько шагов обработки. И я с ними соглашусь – конечно можно, если у вас не ограниченный запас времени и средств. Во всех остальных случаем нужно, как минимум, знать возможности инструмента, которым пользуешься каждый день.

Точка останова(breakpoint)

Самый простой способ использование отладчика, это поставить точку останова, получить прерывание программы, узнать какие есть значения и по шагам посмотреть, как идёт обработка переменных. Но давайте рассмотрим вот такой пример, упрощённый, для понимания ситуации:

for (int i = 10; i >= -10; i--)
{
    var result = 100 / i;
    Console.WriteLine(result);
}

Сразу понятно, что здесь будет проблема из-за деления на ноль. Но, ведь это упрощенный пример. И, допустим, что вы знаете что ваша программа "падает", когда i принимает 0. Но, чтобы попасть в такую ситуацию, многие используют НЕВЕРНЫЕ подходы, например:

  1.  Поставить точку останова жать F5 и следить за изменением i.
  2. Дополнить код следующим образом:
            for (int i = 10; i >= -10; i--)
            {
                if (i == 0)
                {
                    var breakpoint = true;
                }
                var result = 100 / i;
                Console.WriteLine(result);
            }

И поставить точку останова в операторе if, или более удобный вариант с использованием Debugger.Break();

НЕ делайте так! Ведь для этого есть куда более удобный и действенный способ. Поставьте точку останова, затем наведите на неё мышкой и выберете Settings, затем Conditions и в Conditional Expression запишите i == 0

Conditional Expression в параметрах точки останова

После внесения изменений можно нажать на Close, чтобы меню Settings не занимало место. А ваша точка останова будет прерывать работу программы только когда i станет равно нулю. Можно писать сложные выражения, используя несколько параметров, а не один, как в показанному примере.

Также выбрать нужные параметры, вы можете, нажав на точку останова правой клавишей мыши:

Параметры точки останова при нажатии правой клавишей мыши

Здесь же становятся доступны необходимые действия и видны горячие клавиши для их вызова.

Помимо "Conditional Expression", есть еще такой параметр как "Hit Count". Данный параметр срабатывает, когда точка останова была "задета" (строка, на которой установлена данная точка останова была вызвана) какое-то количества раз равное, кратное или больше либо равно указанному.

Использование Hit Count для настройки точки останова

Это позволяет вам прерываться, например, когда значения четные или при каждом сотом вызове.

Conditional Filter позволяет настраивать прерывание когда вы работаете с потоками, процессами или код выполняется на машине с определённым именем.

Использование Conditional Filter для настройки точки останова

Actions

Если вы хотите получать какую-то информацию из кода, при этом не меняя его, вы можете воспользоваться возможностями Actions. Немаловажным является наличии параметра "Continue execution", который позволяет не делать прерывания программы на точке останова.

Выводить можно следующую информацию:

  • В фигурных скобках можно выводить значения переменных, функций. То есть вы можете выводить не только значения самих переменных, но и значения, уже обработанные какими-то функциями.
  • $ADDRESS — текущая инструкция. Например "ShowDebugs.Program.Main(string[]) + 0x00000047"
  • $CALLER — функция, из которой была вызвана текущая. Если цикле примера я вызову функцию, то в ней выведет "ShowDebugs.Program.Main"
  • $CALLSTACK — стек вызовов
  • $FUNCTION — имя текущей функции. Например, "ShowDebugs.Program.Main(string[])"
  • $PID — идентификатор процесса. Например, "0x3870"
  • $PNAME — название процесса. Например, "C:\Users\FlashPC\source\repos\ShowDebugs\ShowDebugs\bin\Debug\ShowDebugs.exe"
  • $TID — идентификатор потока. Например, "0x3E58"
  • $TNAME — название потока. Например, "Main Thread"
Допустимые параметры в Actions при настройке точки останова

Стоит обратить внимание на то, что изменять параметры отображаемой информации вы можете прямо во время выполнения программы.

В процессе работы с отладчиком, может получиться ситуации, когда вы поставили излишнее количество точек останова, которые начинают мешать. Для удобной работы с множеством точек останова можно вызвать окно "Breakpoints" (DebugWindows - Breakpoints)

В нем можно увидеть все установленные точки останова. Удалить не нужные или настроить существующие:

Окно Breakpoints, содержащее все имеющиеся точки останова

В Labels вы можете записывать данные, позволяющие вам быстро идентифицировать нужную точку останова, если есть необходимость сохранять активными большое их количество.

"Set next statement to here" и "immediate window"

"Set next statement to here" полезна тем, что вы можете вернуться в коде к более раннему состоянию.

Используя "immediate window" вы можете как получать сведения о различных элементах кода, так и задавать состояния различным переменным. Рассмотрим работу одного из ранее созданных чат-ботов.

Пример кода чат-бота для демонстрации возможности возвращаться в коде для отладки

Запустив чат-бот и выполнив команду help, я попадаю в выставленную точку останова. Зайдя в "immediate window" пишу "user" и нажимаю enter.

Использование immediate window

В удобном виде я могу увидеть значения всех используемых параметров.

Теперь я вернусь в строку получения пользователя. Для этого нужно навести курсор на требуемую строчку, нажать на Ctrl и когда появится желтая стрелка нажать на её.

Демонстрация работы Set next statement to here

После этого текущая строка для обработки поменяется на указанную а я, например, смогу изменить локаль пользователя. Записав в "immediate window" строку «user.Locale = "en-US"»

Изменение значения переменных используя окно immediate window

Значение будет изменено. Двигаясь дальше по строчкам кода можно будет заметить, что код отработает уже для изменённой локали. И всё это делается очень быстро, без необходимости перезапускать проект.

Также стоит заметить, что в окне "immediate window" поддерживается использования IntelliSense. Нажмите Ctrl+Space и вы увидите все доступные переменные и функции, которые вы можете использовать.

Заострю внимание, что в "Immediate Window" можно запрашивать вывод значений для сложных вещей. Например, можно запросить вызов получения данных из базы данных, одним из используемых вами методом:

Получение сложных данных используя окно immediate window

Используйте LINQ для получения более детальной информации. Он так же поддерживается.

Diagnostic Tools

Говорить про отладку и не рассказать про "Diagnostic Tools" было бы большим упущением. Запущу тот же чат-бот, отправлю команду и посмотрю, что мне приходит.

Окно Diagnostic Tools

Доступна информация по использованию оперативной памяти, загрузке процессора, количество обработанных событий, количество исключений.

Получение информации о событиях в Diagnostic tools

Взглянув в Exception, можно отреагировать на произошедшие исключения.

Список событий, которые выводятся в общий список можно настраивать, отображая только то, за чем необходимо следить в данный момент:

Фильтрация необходимых событий в Diagnostic tools

Если вы используете, например, Entity Framework, то здесь вы можете увидеть код сгенерированных и отправленных SQL запросов. Что позволяет их легко отслеживать и оптимизировать.

Щелкнув два раза по такому событию, вы можете увидеть место, из которого оно было вызвано:

Получение места вызова сгенерированных SQL запросов используя Diagnostic tools

Также вы можете получить весь сгенерированный SQL запрос.

Получение сгенерированных SQL запросов используя Diagnostic tools

Если у вас есть проблемы с производительностью, подобная информация, порой очень сильно упрощает поиск узких мест.

Используя "Diagnostic tools" вы так же можете исследовать использование оперативной памяти вашим приложением и нагрузку на CPU.

Конечно вы можете использовать такие вещи как, например, dotMemory и dotTrace. Но подавляющее большинство проблем можно обнаружить и средствами Visual Studio.

DebuggerDisplay

Для более удобного отображения выводимой информации можно использовать возможности атрибута DebuggerDisplay. О нём я уже писал в далёком 2015. Повторяться я не буду. Кто не в курсе что это такое, рекомендую ознакомиться http://flash2048.com/post/DebuggerDisplay

Отладка — это то, с чем действительно приходится сталкиваться всем разработчикам. Знание данного инструмента обязательно. Отладчик Visual Studio очень мощный и удобный, используя его можно находить проблемы практически любой сложности. А знание описанного функционала может здорово сэкономить вам время и нервы.

Если я забыл указать какие-то дополнительные инструменты Visual Studio, которые удобно использовать для для повышение качества отладки, свяжитесь со мной, с удовольствием добавлю информацию о них.

А вообще — всем кода без ошибок.

Приятного программирования.

Комментарии (1) -

Николай 07.12.2017 7:24:53

Спасибо за статью!

Добавить комментарий