Разбираемся с условными брейкпоинтами в C++

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

Для большинства случаев дебаггинга вам должно с головой хватать стандартных точек останова (breakpoints или брейкпоинтов). Но иногда кода для проверки, объектов или случаев попросту слишком много. Что делать, если мы хотим отфильтровать код, генерирующий точку останова? Прошу вас поприветствовать условные точки останова!

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

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

Вот наш код:

// Делаем несколько прямоугольников большими
// left, top, right, bottom
rects[7] = { 10, 100, 200, 0 }; 
rects[17] = { 10, 100, 200, 0 };
rects[37] = { 10, 100, 200, 0 };
    
ScanForInvalidRects(rects);

for (auto &r : rects)
{
  ScanRectangle(r);
}

ScanForInvalidRects(rects);

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

Рисунок 1: Установка точки останова для перехвата интересующих нас прямоугольников
Рисунок 1: Установка точки останова для перехвата интересующих нас прямоугольников

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

Как вы могли заметить, в Visual Studio 2015 значительно улучшили диалоговое окно для добавления условий (Conditions) и действий (Actions). Например, вы можете открыть его и продолжать редактировать код. Ранее (как, например, в Visual Studio 2013, показанном на рисунке 2) все окна для условий (“Filter”, “Condition” и “When Hit”) были стандартными модальными окнами. Более того, само по себе окно намного чище.

Рисунок 2: Для сравнения аналог окна из Visual Studio 2013 
Рисунок 2: Для сравнения аналог окна из Visual Studio 2013 

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

Expression Evaluator (встроенное средство вычисления выражений) — мы можем писать код внутри редактора условий, но есть некоторые ограничения: вы не можете вызывать код, который имеет какие-либо побочные эффекты, создает новые переменные, содержит new/delete или макросы. К сожалению, это также означает, что мы не можем вызвать пользовательскую функцию с локальными переменными, поскольку она изменяет текущее состояние приложения.

Но у нас в арсенале есть ряд встроенных функций string ('strlen', 'strcmp', 'strst', ...), system ('GetLastError') и некоторые математические функции.

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

Но это еще не все.

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

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

* Счетчик срабатываний (Hit Count): точка останова будет срабатывать после заданного количества итераций, например, каждый пятый раз или только в десятый, или после сотой итераций.

* Фильтр (Filter): позволяет фильтровать точки останова на данной машине, процессе или потоке.

Хотя это и не является условием, в окне установки условной точки останова вы можете указать “действие” (action), которое будет выполняться при попадании в точку останова. Например, мы можем вывести значение переменной или текущее состояние стека. Это очень удобно, поскольку означает, что мы можем динамически вставлять трассировочные операторы без перекомпиляции кода.

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

Код примера можно найти в моем репозитории на GitHub.

Ссылки:

MSDN: Expressions in the Debugger
StackOverflow: Conditional breakpoint: This expression has side effects and will not be evaluated
MSDN: New Breakpoint Configuration Experience in Visual Studio 2015
MSDN: Conditional Breakpoints


Статья подготовлена в преддверии старта курса "C++ Developer. Professional".

А уже сегодня вечером состоится открытое занятие «ООП глазами C++». Хоть и модно критиковать ООП-подход к разработке кода, он остаётся самым популярным во многих и многих сферах. Поэтому не знать и не уметь использовать данную парадигму разработки для настоящего профессионала просто не вежливо. На вебинаре поговорим и посмотрим на примерах о том, как термины ООП реализуются в синтаксисе языка C++. Регистрируйтесь по ссылке.

Источник: https://habr.com/ru/company/otus/blog/689212/


Интересные статьи

Интересные статьи

Субботний вечер омрачен скандалом - сайт не работает, провайдер негодяй, админы - не специалисты, а сервера - решето. Вызов принят, или почему при всей нелюбви к 1С-Битри...
Пандемия COVID-19 стала катализатором для новых полезных сервисов. Например, Zoom стал настолько успешным, что по стоимости обогнал в этом месяце IBM. Нас вдохновил этот пример, и мы...
Привет! В этой статье я бы хотел рассказать об особенностях реализации графического пользовательского интерфейса с виджетами на микроконтроллере и как при этом иметь и привычный по...
В этой статье мы рассмотрим, как система управления 1С-Битрикс справляется с большими нагрузками. Данный вопрос особенно актуален сегодня, когда электронная торговля начинает конкурировать по обороту ...
Как обновить ядро 1С-Битрикс без единой секунды простоя и с гарантией работоспособности платформы? Если вы не можете закрыть сайт на техобслуживание, и не хотите экстренно разворачивать сайт из бэкапа...