что такое отладка кода в программировании

Отладка программы

Отла́дка — этап разработки компьютерной программы, на котором обнаруживают, локализуют и устраняют ошибки. Чтобы понять, где возникла ошибка, приходится :

Существуют две взаимодополняющие технологии отладки.

Содержание

Место отладки в цикле разработки программы

Типичный цикл разработки, за время жизни программы многократно повторяющийся, выглядит примерно так:

Инструменты

Способности программиста к отладке — это, по-видимому, важнейший фактор в обнаружении источника проблемы, но сложность отладки сильно зависит от используемого языка программирования и инструментов, в частности, отладчиков.

Инструменты отладки

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

Также полезными инструментами в руках программиста могут оказаться:

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

«Наш личный выбор — стараться не использовать отладчики, кроме как для просмотра стека вызовов или же значений пары переменных. Одна из причин этого заключается в том, что очень легко потеряться в деталях сложных структур данных и путей исполнения программы. Мы считаем пошаговый проход по программе менее продуктивным, чем усиленные размышления и код, проверяющий сам себя в критических точках.

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

Слепое блуждание в отладчике, скорее всего, непродуктивно. Полезнее использовать отладчик, чтобы выяснить состояние программы, в котором она совершает ошибку, затем подумать о том, как такое состояние могло возникнуть. Отладчики могут быть сложными и запутанными программами, особенно для новичков, у которых они вызовут скорее недоумение, чем принесут какую либо пользу…»

«Отладка сложна и может занимать непредсказуемо долгое время, поэтому цель в том, чтобы миновать большую её часть. Технические приёмы, которые помогут уменьшить время отладки, включают хороший дизайн, хороший стиль, проверку граничных условий, проверку правильности исходных утверждений и разумности кода, защитное программирование, хорошо разработанные интерфейсы, ограниченное использование глобальных переменных, автоматические средства контроля и проверки. Грамм профилактики стоит тонны лечения.»

Инструменты, снижающие потребность в отладке

Другое направление — сделать, чтобы отладка нужна была как можно реже. Для этого применяются:

Безопасность программного кода и отладка

В программном коде может быть так называемое недокументированное поведение — серьёзные ошибки, которые не проявляются при нормальном ходе выполнения программы, однако весьма опасны для безопасности всей системы в случае целенаправленной атаки. Чаще всего это результат ошибок программиста. Наиболее известные примеры — это SQL-инъекция и переполнение буфера. В данном случае задача отладки это:

Источник

Что такое отладка?

Отладчик Visual Studio — очень эффективное средство. Прежде чем приступать к его использованию, следует ознакомиться с базовыми терминами, такими как отладчик, отладка и режим отладки. Когда позднее мы будем вести речь о поиске и устранении ошибок, мы будем иметь в виду то же самое.

Отладчик и отладка

Термин отладка может иметь разные значения, но в первую очередь он означает устранение ошибок в коде. Делается это по-разному. Например, отладка может выполняться путем проверки кода на наличие опечаток или с помощью анализатора кода. Код можно отлаживать с помощью профилировщика производительности. Кроме того, отладка может производиться посредством отладчика.

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

Режим отладки и выполнение приложения

При первом запуске приложения в Visual Studio его можно запустить, нажав кнопку с зеленой стрелкой что такое отладка кода в программированиина панели инструментов (или клавишу F5). По умолчанию в раскрывающемся списке слева отображается элемент Отладка. Если вы не имеете опыта работы с Visual Studio, может показаться, что отладка приложения — это практически то же самое, что его запуск. На самом деле эти задачи хоть и связаны, но коренным образом различаются.

что такое отладка кода в программировании

Значение Отладка соответствует конфигурации отладки. Когда вы запускаете приложение (нажимая зеленую стрелку или клавишу F5) в конфигурации отладки, оно запускается в режиме отладки. Это означает, что приложение запускается с присоединенным отладчиком. В результате вы получаете полный набор функций отладки, которые можно использовать для поиска ошибок в приложении.

Если у вас открыт проект, выберите в раскрывающемся списке Отладка элемент Выпуск.

что такое отладка кода в программировании

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

Когда следует использовать отладчик

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

Следующие шаги

Из этой статьи вы узнали общие принципы отладки приложений. Теперь вы можете приступить к знакомству с процессом отладки в Visual Studio и написанию кода с меньшим количеством ошибок. В следующих статьях приводятся примеры кода на C#, но основные понятия применимы ко всем языкам, поддерживаемым средой Visual Studio.

Источник

Отладка как процесс

Существует мнение, что разработка занимает около 10% времени, а отладка — 90%. Возможно, это утверждение утрировано, но любой разработчик согласится с тем, что отладка — крайне затратный по ресурсам процесс, особенно в больших многопоточных системах.

Таким образом, оптимизация и систематизация процесса debugging’а может приносить весомые плоды в виде сэкономленных человеко-часов, повышения скорости решения проблем и, в конце концов, увеличения лояльности ваших пользователей.

что такое отладка кода в программировании

Сергей Щегрикович (dotmailer) на конференции DotNext 2018 Piter предложил взглянуть на отладку как на процесс, который может быть описан и оптимизирован. Если вы до сих пор не имеете четкого плана поиска багов — под катом видео и текстовая расшифровка доклада Сергея.

(А еще в конце поста мы добавили обращение Джона Скита ко всем дотнетчикам, обязательно посмотрите)

Моя цель — ответить на вопрос: как фиксить баги эффективно и на чем должен быть фокус. Я думаю, что ответ на этот вопрос — процесс. Процесс debugging’а, который состоит из очень простых правил, и вы хорошо их знаете, но, наверно, используете неосознанно. Поэтому моя задача — это систематизировать их и на примере показать как стать более эффективными.

Мы выработаем общий язык общения во время отладки, а также увидим прямой путь к поиску основных проблем. На своих примерах я покажу что получалось из-за нарушения этих правил.

Утилиты отладки

Конечно, любой debugging невозможен без утилит для отладки. Моими любимыми являются:

Падающий сервис

Начнем с примера из моей жизни, в котором я покажу, как бессистемность процесса debugging’а ведет к неэффективности.

Наверно, у каждого такое бывало, когда ты приходишь в новую компанию в новую команду на новый проект, то с самого первого дня хочется нанести непоправимую пользу. Так было и у меня. В то время у нас был сервис, который на вход принимал html, а на выход выдавал картинки.

Сервис был для нас не критичен и мы могли это пережить. Но к проекту подключился я и первое, что решил сделать — исправить это.

Компилируем, деплоим, сервис падает, ошибок нет. За этим процессом проходит три дня, теперь уже приходят мысли о том, что надо наконец-то начать думать и делать что-нибудь другое. Делать можно много чего: попробовать воспроизвести ошибку на локальной машине, смотреть дампы памяти и тд. Казалось, еще дня два и я пофикшу этот баг…

Я смотрел в PerformanceMonitor, где видел сервис, который падает, потом поднимается, потом снова падает. Это состояние называется отчаяние и выглядит вот так:

В этом разнообразии меток ты пытаешься понять, где же на самом деле проблема? После нескольких часов медитации проблема вдруг обнаруживается:

Красная линия — это количество нативных handle’ов, которыми владеет процесс. Нативный handle — это ссылка на ресурс операционной системы: файл, реестр, ключ реестра, мьютекс и тд. По какому-то непонятному стечению обстоятельств падение роста количества handle’ов совпадает с моментами падения сервиса. Это наталкивает на мысль о том, что где-то есть утечка handle’ов.

Берем дамп памяти, открываем его в WinDbg. Начинаем выполнять команды. Попробуем посмотреть очередь финализации тех объектов, которые должны быть освобождены приложением.

В самом конце списка я нашел web-браузер.

Решение простое — взять WebBrowser и вызывать для него dispose :

Выводы из этой истории можно сделать такие: две недели — это долго и слишком много, чтобы найти невызванный dispose ; то, что мы нашли решение проблемы — везение, так как не было какого-то определенного подхода, не было системности.

После этого у меня возник вопрос: а как дебажить эффективно и что для этого делать?

Для этого надо знать всего три вещи:

Правила отладки

Повтори ошибку. Очень простое правило, поскольку, если ты не можешь повторить ошибку, то, возможно, и фиксить нечего. Но бывают разные случаи, особенно это касается багов в многопоточной среде. У нас как-то была ошибка, которая появлялась только на процессорах Itanium и только на продакшн-серверах. Поэтому первая задача в процессе отладки — найти такую конфигурации тестового стенда, на которой бы ошибка воспроизводилась.

Если ты не исправил ошибку, то она не исправлена. Иногда бывает такое: в баг-трекере лежит баг, который появлялся пол года назад, уже его давно никто не видел, и есть желание его просто закрыть. Но в этот момент мы упускаем шанс на знание, шанс на то, чтобы понять как работает наша система и что с ней действительно происходит. Поэтому любой баг — это новая возможность что-то выучить, узнать больше о своей системе.

Пойми систему. Брайан Керниган сказал как-то, что если мы были такие умные, чтобы написать эту систему, то нам нужно быть вдвойне умными, чтобы её дебажить.

Небольшой пример к правилу. Наш мониторинг рисует графики:

Это график количества запросов, обработанных нашим сервисом. Однажды посмотрев на него мы пришли к идеи о том, что можно было бы увеличить скорость работы сервиса. В этом случае график поднимется, возможно, удастся уменьшить количество серверов.

Оптимизация web-performance делается просто: берем PerfView, запускаем его на продакшн-машине, он снимает trace в течении 3-4 минут, мы этот trace забираем на локальную машину и начинаем его изучать.

Одна из статистик, которую показывает PerfView — garbage collector.

Посмотрев на эту статистику мы увидели, что 85% времени сервис тратит на сборку мусора. Можно в PerfView увидеть где конкретно тратится это время.

В нашем случае — это создание строк. Исправление напрашивается само самой: заменяем все string’и на StringBuilder’ы. Локально получаем прирост производительности на 20-30%. Деплоим на продакшн, смотрим результаты в сравнении со старым графиком:

Правило «Пойми систему» — это не только о том, чтобы понять как в вашей системе происходят взаимодействия, как ходят сообщения, а о том, чтобы попробовать смоделировать свою систему.

В примере график показывает пропускную способность. Но если посмотреть на всю систему с точки зрения теории очередей, то окажется, что пропускная способность нашей системы зависит только от одного параметра — от скорости прихода новых сообщений. По факту в системе просто не было больше 80 сообщений единовременно, поэтому оптимизировать этот график не получится никак.

Проверь штепсель. Если открыть документацию любого домашнего прибора, то там обязательно будет написано: если прибор не работает, проверь, что вилка вставлена в розетку. После нескольких часов в отладчике часто ловлю себя на мысли, что надо было просто перекомпилировать, либо просто забрать последнюю версию.

Правило «проверь штепсель» — это про факты и данные. Отладка не начинается с запуска WinDbg или PerfView на продакшн-машинах, она начинается с проверок фактов и данных. Если сервис не отвечает, возможно он просто не запущен.

Разделяй и властвуй. Это первое и, наверно, единственное правило, которое включает в себя отладку как процесс. Оно про гипотезы, их выдвижение и проверку.

Один из наших сервисов не хотел останавливаться.

Делаем гипотезу: возможно, в проекте есть цикл, который бесконечно что-то обрабатывает.

Проверить гипотезу можно по-разному, один из вариантов — это взять дамп памяти. Из дампа вытаскиваем call-stack’и всех потоков с помощью команды

Делаем вторую гипотезу: возможно, у нас deadlock одной задачи на вторую. Чтобы это проверить, можно через WinDbg посмотреть каждую задачу по-отдельности.

Оказывается, одна из задач упала, а вторая — нет. В проекте мы увидели такой код:

Он означает, что инициализационная задача открывает connection и после этого выставляет TaskCompletionSource в true. А что, если здесь упадет Exception? Тогда мы не успеваем выставить SetResult в true, поэтому fix к этому багу был такой:

В этом примере мы выдвигали две гипотезы: о бесконечном цикле и о deadlock’e. Правило «разделяй и властвуй» помогает локализовать ошибку. Последовательными приближениями и решаются такие проблемы.

Самое важное в этом правиле — это гипотезы, поскольку со временем они превращаются в паттерны. И в зависимости от гипотезы мы применяем разные действия.

Освежись. Это правило о том, что надо просто встать из-за стола и пройтись, выпить воды, сока или кофе, сделать что угодно, но самое главное — отвлечься от своей проблемы.

Есть очень хороший метод под названием «уточка». Согласно методу мы должны рассказать о своей проблеме уточке. В качестве уточки можно использовать коллегу. Причем, ему не обязательно отвечать, достаточно слушать и соглашаться. И зачастую, после первых проговоров проблемы, ты сам находишь решение.

Это твой баг. Об этом правиле расскажу на примере.

Для меня это вылилось в 11 месяцев работы с поддержкой Microsoft, конечно, не ежедневно, но от начала до fix’а прошло именно 11 месяцев. Кроме этого, мы отправили им десятки гигабайт дампов памяти, мы ставили сотни private-сборок, чтобы поймать эту ошибку. И все это время мы не могли сказать нашим клиентам, что виновата Microsoft, а не мы. Поэтому баг всегда ваш.

Пять почему. Мы у себя в компании используем Elastic. Elastic хорош для агрегации логов.

Ты приходишь с утра на работу, а Elastic лежит.

Вопросы «почему?» помогают найти корень проблемы. В примере мы много раз могли свернуть с правильного пути, но полный fix выглядит так: обновляем плагин, запускаем сервисы, наращиваем память и делаем пометку на будущее, что в следующий раз, при добавлении новых узлов в кластер, нужно убедиться в достаточности памяти на Master Nodes.

Алгоритм отладки

Впервые про алгоритм отладки я прочитал в книге Джона Роббинса «Debugging applications». Он описывает процесс отладки так:

Этот алгоритм полезен своим внутренним циклом — работой с гипотезой.

С каждым витком цикла мы можем себя проверить: знаем ли мы больше о системе или нет? Если мы выдвигаем гипотезы, проверяем, они не срабатывают, мы не узнаем ничего нового о работе системы, то, наверно, пора освежиться. Два актуальных вопроса на этот момент: какие гипотезы ты уже проверил и какую гипотезу проверяешь сейчас.

Этот алгоритм очень хорошо согласуется с правилами отладки, о которых мы говорили выше: повтори ошибку — это твой баг, опиши проблему — пойми систему, сформулируй гипотезу — разделяй и властвуй, проверь гипотезу — проверь штепсель, убедись что исправлено — пять почему.

На этот алгоритм у меня есть хороший пример. На одном из наших web-сервисов падал exception.

Первая наша мысль — это не наша проблема. Но по правилам, это все-таки проблема наша.

Во-вторых, пытаемся описать проблему: если пользователь делает http-запрос на наш сервис в момент, когда StructureMap пытается сделать новую зависимость, то в этом случае происходит исключение.

В-третьих, выдвигаем гипотезу о том, что StructureMap — это wrapper и внутри что-то есть, что кидает внутреннее исключение. Проверяем гипотезу с помощью procdump.exe.

Исследуя call-stack этого исключения понимаем, что оно происходит внутри object-builder’а в самом StructureMap.

Но NullReferenceException — это не сама проблема, а следствие. Нужно понять где оно возникает и кто его генерирует.

Итак, алгоритм отладки — это интуитивный алгоритм, который существенно экономит время. Он делает упор на гипотезу — а это самое главное в отладке.

Проактивная отладка

По своей сути проактивная отладка отвечает на вопрос «что произойдет, когда появится баг».

Важность техники проактивной отладки можно увидеть на диаграмме цикла жизни бага.

Проблема в том, что чем дольше баг живет, тем больше мы ресурсов (времени) на него тратим.

Правила отладки и алгоритм отладки фокусируют нас на моменте, когда баг найден и мы можем придумать что дальше с ним делать. На самом же деле мы хотим сместить свой фокус на момент создания бага. Я считаю, что мы должны делать Minimum Debuggable Product (MDP), то есть такой продукт, который имеет минимально необходимый набор инфраструктуры для эффективной отладки в продакшене.

MDP состоит из двух вещей: фитнес-функции и USE метода.

Фитнес-функции. Были популяризированы Нил Фордом и соавторами в книге «Building Evolutionary Architectures ». По своей сути фитнес-функции, по мнению авторов книги, выглядят так: есть архитектура приложения, которую мы можем разрезать под разными углами, получая такие свойства архитектуры, как maintainability, performance и прочее, и на каждый такой разрез мы должны писать тест — фитнес-функцию. Таким образом, фитнес-функция — это тест на архитектуру.

В случае MDP, фитнес-функция — это проверка debuggability. Для написания таких тестов можно использовать все что угодно: NUnit, MSTest и тд. Но, поскольку, отладка — это, зачастую, работа с внешними tool’ами, я покажу на примере использование Pester’а (powershell unit testing framework). Его плюс здесь в том, что он хорошо работает с командной строкой.

Например, внутри компании мы договариваемся, что будем использовать конкретные библиотеки для логирования; при логировании мы будем использовать конкретные паттерны; pdb-символы должны быть отданы всегда на symbol server. Это и будет являться теми условностями, которые мы будем проверять в наших тестах.

Этот тест проверяет, что все pdb-символы были отданы на symbol server и были отданы правильно, то есть те, которые содержат номера строк внутри. Для этого берем скомпилированную версию продакшена, находим все exe- и dll-файлы, пропускаем все эти бинарники через утилиту syschk.exe, которая входит в пакет «Debugging tools for windows». Утилита syschk.exe сверяет бинарник с symbol server’ом и, если находит там pdb-файл, печатает отчет об этом. В отчете мы ищем строку «Line numbers: TRUE». И в финале проверяем, чтобы результат был не «null or empty».

Такие тесты необходимо встраивать в continuous deployment pipeline. После того, как прошли интеграционные тесты и unit-тесты, запускаются фитнес-функции.

Покажу ещё один пример с проверкой нужных библиотек в коде.

В тесте мы берем все файлы packages.config и пытаемся найти в них библиотеки nlog. Аналогично мы можем проверить, что внутри поля nlog используется поле correlation id.

USE методы. Последнее, из чего состоит MDP — это метрики, которые нужно собирать.

Продемонстрирую на примере метода USE, который был популяризирован Бренданом Греггом. Идея простая: если в коде есть какая-то проблема, достаточно взять три метрики: utilization (использование), saturation (насыщение), errors (ошибки), которые помогут осознать где проблема.

Некоторые компании, например Circonus (они делают monitoring soft), свои дашборды выстраивают в виде обозначенных метрик.

Если посмотреть детально, например, на память, то использование — это количество свободной памяти, насыщение — это количество обращений к диску, ошибки — это любые ошибки, которые появлялись. Поэтому чтобы делать удобные для отладки продукты, нужно собирать USE-метрики для всех фич и всех частей подсистемы.

Если взять какую-нибудь бизнес-фичу, то, скорее всего, в ней можно выделить три метрики:

Первая гипотеза, которую мы сделали, — сервис упал и надо его запустить заново. При проверке оказывается, что сервис работает, использует 4-5% CPU.

что такое отладка кода в программировании

Вторая гипотеза — внутри сервиса падает ошибка, которую мы не видим. Воспользуемся утилитой etrace.

Утилита позволяет в realtime подписываться к ETW-events и выводить их на экран.

Следующая гипотеза — кто-то съедает всю память. Согласно дампу памяти, больше всего объектов находится в кэше.

Из кода видно, что каждый час кэш должен очищаться. Но памяти уже не хватало, до очистки даже не доходили. Посмотрим на пример метрики USE для кеша.

По графику сразу видно — возросла память, сразу начались ошибки.

Итак, выводы о том, что же такое проактивная отладка.

Итак, как фиксить баги эффективно?

Источник

Изучаем отладчик, часть первая

Я думаю, вы знаете, что взлом программного обеспечения производится не какими-то мистическими «хакерами» – его осуществляют такие же программисты, как и большинство читающих данную статью. При этом они пользуются тем же инструментарием что и сами разработчики ПО. Конечно, с оговорками, поскольку по большей части инструментарий достаточно специфичен, но, так или иначе, при анализе ПО используется отладчик.

Так как большинство моих статей ориентированы на людей, интересующихся применением защиты в своем ПО, я решил, что подача материала с конкретными кусками кода защиты (наподобие опубликованных ранее) только запутает читателя. Гораздо проще начать от азов и потихоньку давать новый материал на уже готовой базе.

Поэтому в данной статье будет рассмотрен один из базовых инструментов программиста – отладчик.
Цели статьи: рассмотреть основные методы работы с отладчиком, показать его расширенные и редко используемые возможности, дать понимание работы механизмов отладчика на примерах и рассмотреть некоторый набор методов противодействия.

Объем статьи получился неожиданно большим, поэтому я разбил ее на три части:

1.1. Применение точек остановки и модификация локальных переменных

Одним из наиболее часто используемых инструментов встроенного отладчика является точка остановки (BreakPoint – далее BP). После установки BP, программа будет работать до тех пор, пока не достигнет точки остановки, после чего ее работа будет прервана и управление будет передано отладчику.

Самым простым способом установки и снятия BP является горячая клавиша «F5» (или ее аналог в меню «Debug->Toggle breakpoint»). Есть и другие способы, но о них позже.

После того как программа остановлена, мы можем изучить значения локальных переменных процедуры, в которой произошла остановка выполнения приложения, а так же проанализировать стек вызовов, предшествующих вызову данной процедуры. Здесь же мы можем изменить значения этих переменных.

Где ставить ВР – общего ответа конечно же нет. По сути ВР предназначена для облегчения изучения работы кода, в корректности работы которого мы не уверены, либо явно содержащего ошибку, которую мы с ходу не можем обнаружить.

Гораздо проще установить точку остановки и последовательно выполнить каждую строчку кода, чем провести часы за изучением того же самого кода, пытаясь выяснить, в каком месте он начал работать не так, как это было задумано нами.

Давайте рассмотрим следующий пример.

Есть задача: написать код, который 5 раз увеличит значение изначально обниленой переменной на единицу и еще один раз на число 123, после чего выведет результат в виде 10-тичного и 16-тиричного значения. Ожидаемые значения будут следующими: 128 и 00000080.

Допустим, код будет написан с ошибкой:

Данный код будет выводить какие угодно значения, но только не те, какие мы хотели, потому что мы не произвели инициализацию переменной «А» нулем. А так как переменная «А» локальна, значит, она расположена на стеке, и мы никогда не сможем предугадать, какое значение она примет в начале данной процедуры. Но будем считать, что уже конец рабочего дня, мы действительно устали (глаз замылился) и просто забыли написать строчку с инициализацией переменной.

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

что такое отладка кода в программировании

Должно получится примерно так, как на картинке. BP установлен на строчке Inc(A). Слева внизу можно наблюдать значение всех локальных переменных процедуры FormCreate (окно называется «Local Variables»), а именно, переменной Self (она передается неявно и всегда присутствует в методах класса), параметра Sender, и непосредственно локальной переменной «А». Ее значение 19079581. Слева в центре в «WatchList» значение переменной «B».

Даже бегло взглянув на значения обеих переменных и выполненные три строчки кода, мы сможем понять, что значение переменной «А» не соответствует ожидаемому. Так как должно было выполнится два инкремента на единицу и еще одно увеличение на число 123, мы должны были увидеть значением переменной «А» число 125, а раз там другое значение, то это может означать только одно – изначальное значение переменной «А» было не верным.

Для проверки правильности нашего предположения, давайте изменим текущее значение переменной «A» на верное и продолжим выполнение программы, чтобы проверить – те ли результаты вернет процедура, которые ожидались.

Для изменения значений переменных в отладчике предусмотрено два инструмента.

Первый – «Evaluate/Modify», вызывается либо через меню, либо по горячей клавише «Ctrl+F7». Это очень простой инструмент с минимумом функционала, он наиболее часто используется.

что такое отладка кода в программировании

Для изменения в нем значения переменной, достаточно указать новое значение в поле «New value» и нажать клавишу «Enter» или кнопку «Modify».
Второй инструмент – «Inspect», доступен так же либо через меню «Run», либо уже непосредственно из диалога «Evaluate/Modify». Это более продвинутый редактор параметров, о нем чуть позже.

После изменения значения переменной «А», обратите внимание на изменения в списке значений локальных переменных:

что такое отладка кода в программировании

Переменная «А» приняла правильное значение, и теперь мы можем продолжить выполнение нашего приложения нажатием «F9» или через меню, выбрав пункт «Run». В результате такого вмешательства с помощью отладчика, процедура выдаст нам ожидаемые числа 128 и 00000080, и мы уже можем смело исправлять код процедуры, т. к. мы нашли в нём причину ошибки и проверили его исполнение с правильно заданным значением переменной «A».

Теперь вернемся к «Inspect». Помимо двух указанных способов его вызова, он так же вызывается двойным кликом на переменной в окне «Local Variables», либо через контекстное меню при правом клике на ней, либо по горячей клавише «Alt+F5».

Это более «продвинутый» редактор свойств переменных, но его использование оправдано при изменении свойств объектов. Для изменения обычной переменной он несколько не удобен, и вот почему.

При его вызове сначала вы увидите вот такой диалог:

что такое отладка кода в программировании

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

что такое отладка кода в программировании

Лишние телодвижения для такой простой операции, как изменения значения обычной переменной, явно избыточны. Но если его использовать для изменения свойств объектов, то картинка немного поменяется.

Через «Evaluate/Modify» доступ к свойствам объекта несколько затруднен тем, что он не предоставляет информации непосредственно об исследуемом объекте. Например, для получения хэндла канваса формы, нам придется в нем набрать следующий текст: «(Sender as TForm1).Canvas.Handle» – что несколько не удобно, ведь мы можем и опечататься, да и просто банально забыть название того или иного свойства.

В случае с «Inspect» такой проблемы не будет.

К примеру, давайте откроем диалог «Inspect» не для переменной «А», а для переменной Self (которая, как я и говорил ранее, всегда неявно присутствует для всех методов объектов).

что такое отладка кода в программировании

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

1.2. Трассировка (пошаговая отладка)

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

Допустим, мы остановились на заранее установленной нами ВР, проанализировали код и хотим перейти к следующий строчке. В принципе мы можем на ней так же поставить ВР и запустить программу. И для следующей, и для тех, кто после неё.
Практически, выставляя ВР на каждой строчке кода процедуры, мы вручную имитируем то, что умеет делать сам отладчик (подробнее во втором разделе).

А умеет он следующее:

Для примера возьмем такой код:

При выполнении трассировки, в тот момент, когда мы находимся на строчке S.Add(), у нас могут быть два варианта реакции отладчика:

что такое отладка кода в программировании

И отвечает за данный функционал параметр «Use Debug DCUs».

1.3. Подробнее о настройках компилятора

Опции в закладке с настройками компилятора влияют непосредственно на то, какой код будет генерироваться при сборке вашего проекта. Очень важно не забывать, что при изменении любого из пунктов данной вкладки, требуется полная пересборка проекта («Project > Build») для того, чтобы изменения вступили в силу. Данные настройки непосредственно влияют на поведение вашего кода в различных ситуациях, а так же на состав информации, доступной вам при отладке проекта.

Рассмотрим их поподробнее:

Группа «Code generation»

что такое отладка кода в программировании

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

В качестве примера, возьмем код из первой главы и остановимся на той же ВР, но с включенной оптимизацией.

что такое отладка кода в программировании

Как видите, значения ранее доступных переменных Self и Sender, более не доступны. Так же из-за отключенного параметра «Use Debug DCUs» произошло кардинальное изменение в окне «Call Stack», ранее заполненного более подробной информацией о списке вызовов.
Более того, инструмент «Inspect» так же отказывается работать с объектом Self, выдавая следующую ошибку:

что такое отладка кода в программировании

Параметры «Stack Frames» и «Pentiom-safe FDIV»

Описание данных параметров я пропущу – на этапе отладки они не интересны. Вкратце: первый поможет при самостоятельном анализе стека, второй отвечает за нюансы при работе с математическим сопроцессором. Если кого-то интересуют нюансы, то мои координаты для связи в профиле.

Параметр «Record field alignment»

Глобальная настройка выравнивания неупакованных записей, которая может быть изменена локально в пределах модуля директивой «<$Align x>» или «<$A x>»

Для примера рассмотрим следующий код:

Размер данной записи, который мы можем получить через SizeOf(T), будет для каждой из настроек выравнивания свой:

Группа «Syntax options»

что такое отладка кода в программировании

Тут лучше вообще ничего не трогать. Ибо, если постараться, то можно сделать даже так, что стандартная VCL откажется собираться.

Единственно остановлюсь на параметре «Complete boolen eval», ибо периодически некоторые его включают. Он грозит ошибкой при выполнении следующего кода:

Так как, при включении данной настройки, булево выражение будет проверяться целиком, то произойдет ошибка при обращении к Value.Count, не смотря на то, что первая проверка определила, что параметр Value обнилен. А если вы включите (например) параметр «Extended syntax», то данный код у вас вообще не соберется, пожаловавшись на необъявленную переменную Result.

Группа «Runtime errors»

что такое отладка кода в программировании

Параметр «Range checking»

Это один из наиболее востребованных параметров при отладке приложения. Он отвечает за проверку границ при доступе к массиву данных.

В самом простом случае вам будет сгенерировано исключение при выполнении вот такого кода:

Здесь мы просто пытаемся обратится к элементу массива, и в принципе, при отключенной опции «Range checking», если мы не выйдем за границу выделенной памяти, данный код нам грозит только тем, что в заголовке формы появится некая непонятная строка.

что такое отладка кода в программировании

Что неприятно, но некритично для выполнения программы. Гораздо хуже, если вы ошиблись с границами блока при попытке записи в него – в этом случае может произойти разрушение памяти приложения.

Рассмотрим такой пример, оптимизацию отключим:

Как вы думаете, чему будет равно значение числа HazardVariable после выполнения данного кода? Нет, не 100. Оно будет равно 4. Так как мы ошиблись при выборе типа итератора и вместо TMyEnum2 написали TMyEnum1, произошел выход за диапазон границ массива и затерлись данные на стеке, изменив значения локальных переменных хранящихся на нём же.

С включенной оптимизацией ситуация будет еще хуже. Мы получим следующую ошибку:

что такое отладка кода в программировании

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

Поэтому возьмите себе за правило – отладка приложения всегда должна происходить с включенной настройкой «Range checking»!

Так же данный параметр контролирует выход за границы допустимых значений при изменении значения переменных. Например, будет поднято исключение при попытке присвоения отрицательного значения беззнаковым типам наподобие Cardinal/DWORD, или при попытке присвоить значение большее, чем может содержать переменная данного типа, например, при присвоении 500 переменной типа Byte и т. п…

Параметр «I/O cheking»

Отвечает за проверку результатов ввода/вывода при работе с файлами в стиле Pascal.

Не уверен, что еще остался софт, использующий данный подход, но если вы вдруг все еще работаете с Append/Assign/Rewrite и т. п., то включайте данный параметр при отладке приложения.

Параметр «Overflow cheking»

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

Чтобы было проще понять различия между данным параметром и «Range checking», рассмотрим следующий код:

Данный код не поднимет исключения при включенном параметре «Overflow cheking». Хоть здесь и присваиваются переменным не допустимые значения, но не производится математических операций над ними. Однако исключение будет поднято при включенном параметре «Range checking».

А теперь рассмотрим второй вариант кода:

Здесь уже не будет реакции от параметра «Range checking», но произойдет поднятие исключения EIntegerOverflow, за который отвечает «Overflow cheking», на строчках Inc(B) и C := C — 1 из-за того, что результат арифметической операции не может быть сохранен в соответствующей переменной.
Таким образом, при работе с переменными оба параметра взаимодополняют друг друга.

«Overflow cheking» не настолько критичен, как «Range checking», но всё же желательно держать его включенным при отладке приложения.

Небольшой нюанс: если вы вдруг реализуете криптографические алгоритмы, то в них, как правило, операция переполнения является штатной. В таких ситуациях выносите код в отдельный модуль и в начале модуля прописывайте директиву «<$OVERFLOWCHECKS OFF>» для отключения проверки переполнений в текущем модуле.

что такое отладка кода в программировании

С данной вкладкой все очень просто. Все параметры, за исключением параметра «Assertions», никоим образом не влияют на финальный код вашего приложения. В зависимости от активности тех или иных параметров изменяется полнота отладочной информации в DCU файле для каждого модуля. На основе данной информации отладчик производит синхронизацию ассемблерного листинга программы с ее реальным кодом, реализованным программистом, распознает локальные переменные и т. п. При компиляции приложения данная отладочная информация не помещается в теле приложения.
Единственным исключением является параметр «Assertions» – он отвечает за работу процедуры Assert(). Если данный параметр отключен – Assert не выполняется, в противном случае – выполняется, причем его код так же будет помещен в тело приложения на этапе компиляции.

На этапе отладки приложения желательно держать все параметры из групп «Runtime errors» и «Debugging» включенными, и отключать их при финальной компиляции релизного приложения. В Delphi 7 и ниже это придется делать руками, но, начиная с Delphi 2005 и выше, появилась нормальная поддержка билдов проекта, в которой можно указывать данные комбинации флагов персонально для каждого типа сборки.

1.4. Окно стека вызовов («Call Stack»)

Если ВР является нашим основным инструментом при отладке приложения, то «Call Stack» второй по значимости.

Выглядит данное окно следующим образом:

что такое отладка кода в программировании

Он содержит полное описание вызовов, которые были выполнены до того, как отладчик прервал выполнение программы на установленном ВР (или остановился из-за возникновения ошибки). Например, на скриншоте изображен стек вызовов, произошедших при нажатии кнопки на форме. Начался он с прихода сообщения WM_COMMAND (273) в процедуру TWinControl.DefaultHandler.

Имея на руках данный список, мы можем быстро переключаться между вызовами двойным кликом (или через меню «View Source»), просматривать список локальных переменных для каждого вызова («View Locals»), устанавливать ВР на любом вызове.

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

Например вот так будет выглядеть стек вызовов при возникновении ошибки EAbstractError:

что такое отладка кода в программировании

В данном случае достаточно найти самый первый сверху вызов, код которого расположен не в системных модулях Delphi, чтобы с большой долей вероятности сказать, что ошибка именно в нём. Таким вызовом является Unit1.TForm1.Button1Click() — это обработчик кнопки Button1 в котором выполнялся следующий код:

1.5. Работа с расширенными свойствами точек остановки

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

Делается это посредством диалога настроек свойств точки остановки. Вызывается он либо через свойства BP в коде приложения.

что такое отладка кода в программировании

Либо в окне «Breakpoint list» так же через свойства выбранной BP.

что такое отладка кода в программировании

Выглядит диалог настроек следующим образом:

что такое отладка кода в программировании

Параметр «Condition» отвечает за условие срабатывания точки остановки.
Параметр «Pass count» указывает, сколько таких условий нужно пропустить, прежде чем ВР будет активирована, причем подсчёт количества срабатываний ведется от самого первого, с учетом значения параметра «Condition».

Рассмотрим абстрактный пример:

Допустим, теперь мы хотим начать анализ после 75 итерации включительно, для этого выставим следующее условие в параметре «Condition»: I > 75. В этом случае данная ВР сработает всего два раза: в тот момент, когда итератор «I» будет равен 85, и второй раз, при значении 95.

Произошло это по следующим причинам:

В первом случае, когда у нас не было условия, ВР срабатывала на каждой итерации цикла, но т. к. был указан параметр «Pass count», управление не переходило к отладчику, а происходило всего лишь увеличение количество срабатываний ВР до тех пор, пока их количество не становилось равным заданному в «Pass count». Поэтому мы получали управление только каждую десятую итерацию (после чего счетчик обнулялся).

Во втором случае увеличение счетчика сработок начало происходить только после выполнения изначального условия «Condition», т. е., пока итератор «I» был меньше или равен числу 75, отладчик считал, что условие не выполнено и продолжал выполнение программы. Как только первое условие выполнилось, началось увеличение количества срабатываний, которое стало равным значению параметра «Pass count» именно в тот момент, когда итератор «I» достиг значения 85.

Естественно, если мы хотим, чтобы ВР начала срабатывать сразу после превышения итератором «I» числа 75, то параметр «Pass count» необходимо выставить в ноль.

Группируя эти два параметра мы можем более гибко настроить условия срабатывания наших ВР.

Теперь рассмотрим один небольшой нюанс.

Условия передачи управления отладчику, указанные в свойствах ВР, рассчитываются самим отладчиком. Т.е. грубо (взяв за основу вышеописанный пример), не смотря на то, что мы прервались на ВР всего лишь два раза, на самом деле прерывание произошло все 100 раз, просто мы не получали управление в те моменты, которые не соответствовали заданным нами условиям.

Чем это плохо: если подобным образом анализировать достаточно долгий по продолжительности цикл (например, от десяти тысяч итераций и выше), то отладка программы может очень сильно затормозить вашу работу.

Можно проверить на следующем коде:

Установим ВР на той же седьмой строчке и укажем в параметре «Condition» значение I=9999. Даже на таком маленьком цикле нам придётся ждать срабатывания условия в районе 3-5 секунд. Конечно же, это не удобно. В таких случаях проще модифицировать код следующим образом:

… и поставить ВР на Beep, чем ждать столь продолжительное время. В этом случае мы получим управление на практически мгновенно.
(В релизной сборке проекта директива DEBUG будет отсутствовать и отладочный код не попадет в неё, но лучше, после отладки, все же не забывать удалять все эти отладочные Beep-ы. )

Подобные «тормоза» обусловлены тем, что всё взаимодействия отладчика с отлаживаемым приложением происходит через механизм структурной обработки исключений (SEH), более известный Delphi программистам через куцую обертку над ним в виде try..finally..except. Работа с SEH является одной из наиболее «тяжелых» операций для приложения. Дабы не быть голословным и показать его влияние на работу программы наглядно, рассмотрим такой код:

В функции Test1 и Test2 происходит инкремент переданного значения 100 миллионов раз.

В первом случае она выполняется в районе 210 миллисекунд, тогда как во втором случае – в четыре с небольшим раза дольше, а изменений между ними по сути нет – всего лишь глухой try..finally.

Это, кстати тоже вам в «копилочку» – по возможности не вставляйте обработку исключений внутрь циклов, лучше выносите её за пределы…

Не рассмотренным у нас остался параметр «Group», он отвечает за включение BP в определенную группу точек остановки. Группа – понятие условное, на самом деле это некий идентификатор, произвольно задаваемый разработчиком, но удобен он тем, что к данным идентификаторам можно применить групповые операции управляя активностью всех BP, входящих в данную группу.

Групповые операции настраиваются в расширенных настройках ВР:

что такое отладка кода в программировании

Отвечают за это параметры: «Enable group» – активирующий все ВР группы, и «Disable group» – отключающий все ВР входящие в группу.

Так же при групповых операциях часто применяется параметр «Break», который отвечает за действия отладчика при достижении ВР. Если данный параметр не активен, то прерывания выполнения программы при достижении данной ВР не происходит.
Важно – данный параметр не отключает саму ВР.

В общем случае – использование групповых операций применяется в тех случаях, когда отладка при помощи обычных ВР не удобна.

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

Перед компиляцией примера обязательно включите в настройках компилятора опцию «Overflow cheking» и отключите оптимизацию.

После запуска данного кода, произойдет исключение на шестнадцатой строчке

Обычно, для того чтобы разобраться в причинах ошибки, ставят ВР на строку, в которой произошло поднятие исключения, но в данном конкретном примере нам это не поможет. Причина проста: данная строчка десятки раз подряд будет выполнена успешно, и, если мы поставим ВР на ней, то все эти десятки раз нам придется нажимать «F9» до тех пор, пока мы не достигнем непосредственно самого исключения.

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

Сделаем это следующим образом:

Если из описания примера не все понятно — посмотрите ролик, демонстрирующий всю последовательность действий:
rouse.drkb.ru/blog/bp3.mp4 (17 Мб).
(я извиняюсь, но вставить ссылку так, чтобы ролик отображался прямо в теле статьи, у меня не получилось, поэтому только ссылка)

Таким образом, используя всего три ВР и групповые операции над ними, мы достаточно точно локализовали место ошибки и обеспечили удобство отладки кода.

Почему в примере не использовался параметр «Pass Count», а условия задавались через параметр «Condition»? Дело в том, что «Pass Count» просто отключает прерывание на ВР. Сама же ВР выполняется (т. к. условия её выполнения описаны в параметре «Condition») и раз она выполнилась, то выполняются и её групповые операции.

Осталось рассмотреть еще несколько параметров.

Параметр «Ignore subsequent exceptions» отключает реакцию отладчика на любое исключение, возникшее после выполнения ВР с включенным данным параметром.

Параметр «Handle subsequent exceptions» отменяет действие предыдущего параметра, возвращая отладчик в нормальный режим работы.

Чтобы посмотреть как это выглядит, создадим такой код:

На первом ShowMessage поставьте ВР, отключите его, сняв галку с параметра «Break», и включите параметр «Ignore subsequent exceptions».

На втором ShowMessage сделайте то же самое, только включите параметр «Handle subsequent exceptions».

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

Осталось 2 параметра:

«Log message» – любая текстовая строчка, которая будет выводится в лог событий при достижении ВР.

«Eval expression» – при достижении ВР, отладчик вычисляет значение данного параметра и (в случае если включен флаг «Log result») выводит его в лог событий. Значение для вычисления может быть любым, хоть тот же «123 * 2».

1.6. Использование «Data breakpoint», «Watch List» и «Call Stack»

Все, что мы рассматривали ранее, относилось к так называемым «Source Breakpoint». Т. е. к точкам остановки, устанавливаемым непосредственно в коде приложения.

Но, помимо кода, мы работаем с данными (переменными, массивами, просто с участками выделенной памяти) и у отладчика есть возможность устанавливать BP на адреса, по которым эти данные расположены в памяти, при помощи «Data breakpoint».

Установка ВР на адрес памяти производится через «Watch List» (не во всех версиях Delphi) или в окне «Breakpoint List» при помощи «Add Breakpoint->Data Breakpoint», где, в появившемся диалоге, указываем требуемый адрес, размер контролируемой области или имя переменной. В случае указания имени переменной, отладчик попробует вычислить ее расположение в памяти и (если это возможно) установит ВР.

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

Что такое область видимости переменной – вы должны знать. Глобальные переменные доступны нам всегда, и, даже без запуска приложения, отладчик предоставляет нам возможность устанавливать «Data breakpoint» на изменения в таких переменных. Правда, в данном случае он рассчитывает адрес такой переменной на основании предыдущей сборки приложения, и не факт, что он совпадет с ее расположением при следующем запуске. Ситуация гораздо хуже с локальными переменными. Область видимости переменной – это не просто так введенное понятие, локальные переменные расположены на стеке, и, как только они выходят из области видимости, место, занимаемое ими ранее, используется под хранение совершенно других данных. Таким образом установить «Data breakpoint» на локальную переменную можно только в тот момент, пока она не вышла из области видимости.

Те, кто ранее работал с профессиональными отладчиками, вероятно узнают в «Data breakpoint» один из базовых инструментов анализа приложения – «Memory Breakpoint».

К сожалению, отладчик Delphi не позиционируется как профессиональное средство отладки сторонних приложений, поэтому столь полезный инструмент как «Memory Breakpoint» представлен в нем в обрезанном варианте, где от него оставлена только возможность контроля адреса памяти на запись.

Но даже в этаком ограниченном варианте он остается отличным инструментом для контроля изменений в памяти приложения, особенно для отслеживания ошибок при адресной арифметике.

Рассмотрим следующий код:

На первый взгляд как будто все правильно, но запустив программу на выполнение мы получим примерно такую ошибку:

что такое отладка кода в программировании

Нажав на «Break», мы окажемся где-то внутри модуля «system»:

что такое отладка кода в программировании

Код, на котором мы прервались, ничего нам не может сказать о причине возникновения ошибки, но у нас есть окно «Call Stack», на основании которого мы можем сделать вывод, что ошибка произошла при вызове процедуры ShowCaption в главном модуле программы.
Если установить BP в данной процедуре и перезапустить программу, а затем, при срабатывании ВР, проверить значение переменной Caption, то окажется что данная переменная не доступна:

что такое отладка кода в программировании

Это означает, что где-то произошло разрушение памяти и затерлись данные по адресу переменной Caption. Определить это место нам поможет «Data breakpoint».

После выполнения этих действий, программа остановится на строчке №68 – Inc(Value). Особенность «Data breakpoint» в том, что остановка происходит сразу после произошедших изменений, а не при попытке изменения контролируемой памяти, поэтому место, где происходит запись по адресу переменной FP.Caption, находится строчкой выше – это строка Value^ := ValueData[I].

Теперь, найдя проблемное место, мы можем исправить и саму ошибку. Она заключается в том, что длина строки ValueData, которую мы пишем в буфер Data, превышает размер буфера, из-за чего происходит перезапись памяти, в которой расположены переменные Caption и Description.

1.7. В заключение

На этом я заканчиваю краткий обзор возможностей интегрированного отладчика. Осталось несколько нерассмотренных нюансов, как то: настройка игнорируемых исключений, ВР при загрузке модуля и т.п., но они несущественны и крайне редко применяются на практике.
Так же нерассмотренным остался режим отладки в окне «CPU-View» и связанные с ним Address Breakpoint. Его я так же решил пропустить, т.к. читателям не знакомым с ассемблером мое объяснение не даст ничего, а более подкованные специалисты и без меня знают что такое CPU-View и как его правильно применять 🙂

Во второй части статьи, будет рассмотрена программная реализация отладчика. В ней будет показано, что именно происходит при установке BreakPoint, показана обратная сторона Data Breakpoint, не реализованная в отладчике Delphi, показано как в действительности производится трассировка (двумя методами, классический через TF флаг и на основе GUARD страниц), а так же рассмотрен механизм Hardware Breakpoint, тоже отсутствующий в интегрированном отладчике Delphi.

Отдельная благодарность сообществу форума «Мастера Дельфи» за помощь при подготовке статьи, а также персональное спасибо Андрею Васильеву aka Inovet, Тимуру Вильданову aka Palladin и Дмитрию aka Брат Птибурдукова за вычитку материала и ценные советы.

Александр (Rouse_) Багель
Москва, октябрь 2012

Источник

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *