Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Как правило, код, который мы пишем как разработчики программного обеспечения, не всегда делает то, что мы ожидали. Иногда это делает что-то совершенно другое! Когда происходит непредвиденное, следующим шагом будет выяснить, почему. Хотя может возникнуть соблазн просто смотреть на наш код в течение нескольких часов, гораздо проще и эффективнее использовать отладчик или средство отладки.
Отладчик, к сожалению, не то, что может волшебно выявить все проблемы или ошибки в нашем коде. Отладка означает, чтобы выполнить код пошаговые инструкции в средстве отладки, например Visual Studio, чтобы найти точный момент, в котором вы совершили ошибку программирования. Затем вы понимаете, какие исправления необходимо внести в код и средства отладки, которые часто позволяют вносить временные изменения, чтобы продолжить работу программы.
Эффективное использование отладчика — это навык, который занимает много времени и практики, но в конечном счете является основной задачей для каждого разработчика программного обеспечения. В этой статье описаны основные принципы отладки и советы по началу работы.
Уточняйте проблему, задав себе правильные вопросы
Это помогает уточнить проблему, с которыми вы столкнулись, прежде чем попытаться устранить ее. Мы ожидаем, что вы уже столкнулись с проблемой в коде, в противном случае вы не попытаетесь выяснить, как отладить его! Поэтому перед началом отладки убедитесь, что вы определили проблему, которую вы пытаетесь решить:
Что вы ожидали, что ваш код будет делать?
Что произошло вместо этого?
Если при запуске приложения возникает ошибка (исключение), это может быть хорошо! Исключение — это непредвиденное событие, возникаемое при выполнении кода, как правило, ошибка какого-либо типа. Средство отладки может показать точное место в коде, где произошло исключение, и помочь вам исследовать возможные решения.
Если что-то еще произошло, каков симптом проблемы? Вы уже подозреваете, где возникла эта проблема в коде? Например, если в коде отображается какой-то текст, но текст неверный, вы знаете, что данные плохи или код, задающий отображаемый текст, имеет какой-то ошибку. Пошаговое выполнение кода в отладчике позволяет проанализировать каждое изменение переменных, чтобы точно выяснить, когда и как присваиваются неверные значения.
Изучение ваших предположений
Прежде чем исследовать баг или ошибку, думайте о предположениях, которые заставили вас ожидать определенный результат. Скрытые или неизвестные предположения могут помешать идентификации проблемы, даже когда вы смотрите прямо на её причину в отладчике. У вас может быть длинный список возможных предположений! Вот несколько вопросов, которые вы можете задать себе, чтобы бросить вызов своим предположениям.
Вы используете правильный API (то есть правильный объект, функция, метод или свойство)? Api, который вы используете, может не делать то, что вы думаете, что это делает. После проверки вызова API в отладчике исправление может потребовать обращения к документации, чтобы определить правильный API.
Правильно ли вы используете API? Может быть, вы использовали правильный API, но не использовали его правильно.
Содержит ли код какие-либо опечатки? Некоторые опечатки, такие как простая опечатка в имени переменной, могут быть трудно заметны, особенно при работе с языками, которые не требуют объявления переменных перед использованием.
Вы изменили код и предположили, что это не связано с проблемой, которую вы видите?
Вы ожидали, что объект или переменная содержат определенное значение (или определенный тип значения), отличное от того, что действительно произошло?
Знаете ли вы намерение кода? Часто сложнее отлаживать код другого пользователя. Если это не ваш код, возможно, вам может потребоваться потратить время на обучение именно того, что делает код, прежде чем вы сможете эффективно отладить его.
Подсказка
При написании кода начинайте с малого и используйте работающий код! (Хороший пример кода полезен здесь.) Иногда проще исправить большой или сложный набор кода, начиная с небольшого фрагмента кода, демонстрирующего основную задачу, которую вы пытаетесь достичь. Затем можно изменять или добавлять код постепенно, тестируя его на наличие ошибок на каждом этапе.
Подспрошив предположения, вы можете сократить время, необходимое для поиска проблемы в коде. Вы также можете сократить время, необходимое для устранения проблемы.
Пошагово выполните отладку кода, чтобы найти место, где возникла проблема.
При обычном запуске приложения отображаются ошибки и неверные результаты только после выполнения кода. Программа также может неожиданно завершиться, не говоря уже о том, почему.
При запуске приложения в отладчике, который также называется режимом отладки, отладчик активно отслеживает все, что происходит при запуске программы. Кроме того, вы можете приостановить приложение в любой момент, чтобы проверить его состояние, а затем пройтись по коду строчка за строчкой, чтобы наблюдать за всеми деталями, по мере их появления.
В Visual Studio войдите в режим отладки, используя F5 (или команду меню Отладка>, или кнопку Начать отладкуна панели инструментов отладки). Если возникает исключение, помощник по обработке исключений Visual Studio перенаправит вас точно на то место, где произошло исключение, и предоставит дополнительную полезную информацию. Дополнительные сведения об обработке исключений в коде см. в методах отладки и средствах.
Если вы не получили исключение, вероятно, у вас есть хорошее представление о том, где искать проблему в коде. На этом этапе вы используете точки останова в отладчике, чтобы дать себе возможность более внимательно изучить ваш код. Точки останова — это самая базовая и важная функция надежной отладки. Точка останова указывает, где Visual Studio должна приостановить выполнение кода, чтобы просмотреть значения переменных или поведение памяти, последовательность выполнения кода.
В Visual Studio можно быстро задать точку останова, щелкнув в левом поле рядом с строкой кода. Или поместите курсор на строку и нажмите клавишу F9.
Чтобы проиллюстрировать эти понятия, мы рассмотрим пример кода, который уже содержит несколько ошибок. Мы используем C#, но функции отладки применяются к Visual Basic, C++, JavaScript, Python и другим поддерживаемым языкам. Пример кода для Visual Basic также предоставляется, но снимки экрана находятся на C#.
Создание примера приложения (с некоторыми ошибками)
Затем вы создадите приложение с несколькими ошибками.
Необходимо установить Visual Studio и компонент .NET разработка для настольных приложений.
Если вы еще не установили Visual Studio, перейдите на страницу загрузки Visual Studio, чтобы установить программу бесплатно.
Если необходимо установить рабочую нагрузку, но у вас уже есть Visual Studio, выберите Инструменты>Получить инструменты и компоненты. Установщик Visual Studio запускается. Выберите компонент разработки настольных приложений .NET, а затем выберите Изменить.
Откройте Visual Studio.
В окне запуска нажмите кнопку "Создать проект". Введите консоль в поле поиска, выберите C# или Visual Basic в качестве языка, а затем выберите консольное приложение для .NET. Нажмите кнопку Далее. Введите ConsoleApp_FirstApp в качестве имени проекта и нажмите кнопку "Далее".
Если вы используете другое имя проекта, необходимо изменить значение пространства имен, чтобы оно соответствовало имени проекта при копировании примера кода.
Выберите рекомендуемую целевую платформу или .NET 8, а затем выберите Создать.
Если вы не видите шаблон проекта консольного приложения для .NET, перейдите в раздел Tools>Get Tools and Features, который открывает Установщик Visual Studio. Выберите компонент разработки настольных приложений .NET, а затем выберите Изменить.
Visual Studio создает консольный проект, который отображается в обозревателе решений в правой области.
В Program.cs (или Program.vb) замените весь код по умолчанию следующим кодом. (Сначала выберите правильную вкладку языка C# или Visual Basic.)
using System; using System.Collections.Generic; namespace ConsoleApp_FirstApp { class Program { static void Main(string[] args) { Console.WriteLine("Welcome to Galaxy News!"); IterateThroughList(); Console.ReadKey(); } private static void IterateThroughList() { var theGalaxies = new List<Galaxy> { new Galaxy() { Name="Tadpole", MegaLightYears=400, GalaxyType=new GType('S')}, new Galaxy() { Name="Pinwheel", MegaLightYears=25, GalaxyType=new GType('S')}, new Galaxy() { Name="Cartwheel", MegaLightYears=500, GalaxyType=new GType('L')}, new Galaxy() { Name="Small Magellanic Cloud", MegaLightYears=.2, GalaxyType=new GType('I')}, new Galaxy() { Name="Andromeda", MegaLightYears=3, GalaxyType=new GType('S')}, new Galaxy() { Name="Maffei 1", MegaLightYears=11, GalaxyType=new GType('E')} }; foreach (Galaxy theGalaxy in theGalaxies) { Console.WriteLine(theGalaxy.Name + " " + theGalaxy.MegaLightYears + ", " + theGalaxy.GalaxyType); } // Expected Output: // Tadpole 400, Spiral // Pinwheel 25, Spiral // Cartwheel, 500, Lenticular // Small Magellanic Cloud .2, Irregular // Andromeda 3, Spiral // Maffei 1, 11, Elliptical } } public class Galaxy { public string Name { get; set; } public double MegaLightYears { get; set; } public object GalaxyType { get; set; } } public class GType { public GType(char type) { switch(type) { case 'S': MyGType = Type.Spiral; break; case 'E': MyGType = Type.Elliptical; break; case 'l': MyGType = Type.Irregular; break; case 'L': MyGType = Type.Lenticular; break; default: break; } } public object MyGType { get; set; } private enum Type { Spiral, Elliptical, Irregular, Lenticular} } }Наше намерение для этого кода заключается в отображении названия галактики, расстояния до галактики и типа галактики все в списке. Для отладки важно понять намерение кода. Ниже приведен формат одной строки из списка, который мы хотим отобразить в выходных данных:
название галактики, расстояние, тип галактики.
Запуск приложения
Нажмите клавишу F5 или кнопку
на панели инструментов отладки, которая находится над редактором кода.
Приложение запускается и нет исключений, отображаемых для нас отладчиком. Однако результаты, которые вы видите в окне консоли, не соответствуют ожидаемым. Вот что мы должны были увидеть:
Tadpole 400, Spiral
Pinwheel 25, Spiral
Cartwheel, 500, Lenticular
Small Magellanic Cloud .2, Irregular
Andromeda 3, Spiral
Maffei 1, Elliptical
Но вместо этого вы увидите следующие выходные данные:
Tadpole 400, ConsoleApp_FirstApp.GType
Pinwheel 25, ConsoleApp_FirstApp.GType
Cartwheel, 500, ConsoleApp_FirstApp.GType
Small Magellanic Cloud .2, ConsoleApp_FirstApp.GType
Andromeda 3, ConsoleApp_FirstApp.GType
Maffei 1, 11, ConsoleApp_FirstApp.GType
Глядя на выходные данные и наш код, мы знаем, что GType это имя класса, который хранит тип галактики. Мы пытаемся показать фактический тип галактики (например, "Спираль"), а не имя класса!
Отладка приложения
При продолжающемся выполнении приложения вставьте точку останова.
В цикле
foreachщелкните правой кнопкой мыши рядом сConsole.WriteLineметодом, чтобы открыть контекстное меню и выберите в меню пункт Точка останова> — Вставить точку останова во всплывающем меню.foreach (Galaxy theGalaxy in theGalaxies) { Console.WriteLine(theGalaxy.Name + " " + theGalaxy.MegaLightYears + ", " + theGalaxy.GalaxyType); }При установке точки останова красная точка отображается в левом поле.
При возникновении проблемы в выходных данных вы начинаете отладку, просматривая предыдущий код, который задает выходные данные в отладчике.
Щелкните кнопку Перезапустить
(Ctrl + Shift + F5).Приложение приостанавливается в заданной точке останова. Желтое выделение указывает, где отладчик приостановлен (желтая строка кода еще не выполнена).
Наведите указатель мыши на
GalaxyTypeпеременную справа, а затем слева от значка с ключом развернитеtheGalaxy.GalaxyType. Вы видите, чтоGalaxyTypeсодержит свойствоMyGType, а значение свойства установлено вSpiral."Спираль" действительно правильное значение, которое вы ожидали вывести в консоль! Хорошо, что вы можете получить доступ к значению в этом коде при запуске приложения. В этом сценарии мы используем неправильный API. Давайте посмотрим, можно ли исправить это при выполнении кода в отладчике.
В том же коде при отладке по-прежнему поместите курсор в конец
theGalaxy.GalaxyTypeи измените его наtheGalaxy.GalaxyType.MyGType. Хотя вы можете внести изменения, редактор кода отображает ошибку (красная строка с волнистой линией). (В Visual Basic ошибка не отображается, и этот раздел кода работает.)Нажмите F11 (Отладка> или кнопку 'Войти' на панели инструментов отладки), чтобы выполнить текущую строку кода.
F11 перемещает отладчик (и выполняет код) по одной инструкции за раз. F10 (Step Over) — это аналогичная команда, и оба полезны при обучении использованию отладчика.
При попытке перейти к отладчику появится диалоговое окно "Горячая перезагрузка", указывающее, что изменения не могут быть скомпилированы.
Откроется диалоговое окно "Изменить и продолжить", указывающее, что изменения не могут быть скомпилированы.
Замечание
Для отладки кода примера Visual Basic пропустите следующие несколько шагов, пока не будет указано, как щелкнуть значок перезапуска

Выберите «Изменить» в окне сообщения «Горячая перезагрузка» или «Изменение и продолжение». В окне "Список ошибок " появится сообщение об ошибке. Ошибка указывает, что
'object'не содержит определение дляMyGType.Несмотря на то, что мы устанавливаем каждую галактику с объектом типа
GType(который имеетMyGTypeсвойство), отладчик не распознаетtheGalaxyобъект как объект типаGType. Почему? Вы хотите просмотреть любой код, задающий тип галактики. Когда вы делаете это, вы видите, чтоGTypeкласс определенно имеет свойствоMyGType, но что-то не так. Сообщениеobjectоб ошибке оказывается ключом; для интерпретатора языка тип, как представляется, является объектом типаobjectвместо объекта типаGType.Просматривая код, связанный с настройкой типа галактики, вы обнаружите, что свойство класса
Galaxyуказано какobject, а не какGType.public object GalaxyType { get; set; }Измените предыдущий код следующим образом:
public GType GalaxyType { get; set; }Щелкните
CTRL + + ), чтобы перекомпилировать код и перезапустить.Теперь, когда отладчик приостанавливается на
Console.WriteLine, наведите указатель мыши наtheGalaxy.GalaxyType.MyGTypeи убедитесь, что значение правильно задано.Удалите точку останова, щелкнув значок точки останова в левом поле (или щелкните правой кнопкой мыши и выберите Точку останова>Удалить точку останова), а затем нажмите F5, чтобы продолжить.
Приложение запускается и отображает выходные данные. Это выглядит хорошо, но вы заметили одно. Вы ожидали, что Малое Магелланово Облако будет отображаться как нерегулярная галактика в выходных данных консоли, но тип галактики вообще не отображается.
Tadpole 400, Spiral Pinwheel 25, Spiral Cartwheel, 500, Lenticular Small Magellanic Cloud .2, Andromeda 3, Spiral Maffei 1, EllipticalЗадайте точку останова в этой строке кода перед оператором
switch(перед операторомSelectв Visual Basic).public GType(char type)Этот код находится в том месте, где задан тип галактики, поэтому мы хотим более внимательно посмотреть на него.
Щелкните
значок в панели инструментов отладки ("Перезапустить" Ctrl Shift F5 ), чтобы перезапустить.Отладчик приостанавливается в строке кода, в которой устанавливается точка останова.
Наведите указатель мыши на
typeпеременную. Отображается значениеS(после символьного кода). Вы заинтересованы в значенииI, поскольку, как вы знаете, это нерегулярный тип галактики.Нажмите клавишу F5 и снова наведите указатель мыши на
typeпеременную. Повторите этот шаг, пока не увидите значениеIпеременнойtype.
Теперь нажмите клавишу F11 (шаг>).
Нажимайте клавишу F11, пока не остановитесь на линии кода в
switchоператоре для значения 'I' (Selectоператор для Visual Basic). Здесь вы увидите четкую проблему, связанную с опечаткой. Вы ожидали, что код перейдёт к моменту, где он устанавливаетMyGTypeкак нерегулярный тип галактики, но отладчик вместо этого полностью пропускает этот код и приостанавливается вdefaultразделеswitchоператора (Elseоператор в Visual Basic).
Глядя на код, в инструкции
case 'l'отображается опечатка. Оно должно иметь значениеcase 'I'.Выберите в коде
case 'l'и замените его наcase 'I'.Удалите точку останова и нажмите кнопку "Перезапустить ", чтобы перезапустить приложение.
Исправлены ошибки, и вы увидите ожидаемые выходные данные!
Нажмите любую клавишу, чтобы завершить работу приложения.
Сводка
При появлении проблемы используйте отладчик и команды шага , такие как F10 и F11, чтобы найти область кода с проблемой.
Замечание
Если трудно определить регион кода, в котором возникает проблема, установите точку останова в коде, которая выполняется до возникновения проблемы, а затем используйте команды шага, пока не увидите манифест проблемы. Вы также можете использовать точки трассировки для регистрации сообщений в окне вывода . Просмотрев зарегистрированные сообщения (и замечая, какие сообщения еще не зарегистрированы!), часто можно изолировать регион кода с проблемой. Возможно, вам придется повторить этот процесс несколько раз, чтобы сузить его.
При поиске области кода с проблемой используйте отладчик для изучения. Чтобы найти причину проблемы, проверьте код проблемы при запуске приложения в отладчике:
Проверьте переменные и проверьте, содержат ли они тип значений, которые они должны содержать. Если вы нашли плохое значение, узнайте, где задано плохое значение (чтобы найти, где задано значение, может потребоваться перезапустить отладчик, просмотреть стек вызовов или оба).
Проверьте, выполняет ли приложение код, который вы ожидаете. (Например, в примере приложения мы ожидали, что код
switchинструкции должен задать тип галактики нерегулярно, но приложение пропускало код из-за опечатки.)
Подсказка
Вы используете отладчик для поиска ошибок. Средство отладки может найти ошибки для вас только в том случае, если оно знает намерение вашего кода. Средство может только знать намерение кода, если вы, разработчик, выражаете это намерение. Написание модульных тестов — вот как это делается.
Дальнейшие шаги
В этой статье вы узнали несколько общих концепций отладки. Затем вы можете узнать больше об отладчике.