Мгновенное воспроизведение: отладка программ C и C ++ с помощью rr

Мгновенноевоспроизведениеотладкапрограммcиc++спомощьюrr

Instant replay: Debugging C and C++ programs with rr

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

Проект rr позволяет программистам исследовать всю жизнь выполнения программы C или C ++ и воспроизвести код казни, чтобы увидеть, какие действия в прошлом вызвали «ужасные неудачи». rr упакован с Дополнительные пакеты для Enterprise Linux (EPEL) в Red Hat Enterprise Linux (RHEL) и с Fedora 33, 33, 35, а также 35.

rr записывает информацию трассировки о выполнении приложения. Эта информация позволяет многократно воспроизводить конкретную запись сбоя и исследовать ее в GNU Debugger (GDB), чтобы лучше исследовать причину. Помимо воспроизведения трассировки, rr позволяет вам запустить программу в обратном порядке, по сути, позволяя вам «перемотать ленту», чтобы увидеть, что произошло ранее при выполнении программы.

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

Давайте посмотрим, как установить up rr и используйте его в пример, чтобы лучше проиллюстрировать его полезность.

Требования и настройка

Потому что rr использует ряд новых функций ядра Linux и специальный процессор. оборудование для мониторинга производительности, среды, в которых оно работает, ограничены. Новые ядра Fedora имеют необходимую поддержку. Однако, чтобы правильно отслеживать и воссоздавать, когда в потоке происходят асинхронные события, rr использует аппаратные счетчики событий для мониторинга производительности, которые обеспечивают детерминированный подсчет того, когда поток прерывается асинхронным событием. В настоящее время rr поддерживает только эти подсчеты. для процессоров Intel с микроархитектурой Westmere или более новой.

Установка rr в Fedora – это простая задача, требующая одного RPM. Если вы используете RHEL, вам нужно будет включить EPEL. Получив доступ к соответствующим репозиториям, вы можете установить rr следующей командой:

 $ sudo dnf -y install rr 

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

 $ sudo sh -c 'echo 1> / proc / sys / kernel / perf_event_paranoid' 
 

Если вы хотите сделать этот параметр для оборудования мониторинга производительности постоянным, вы также можете добавить следующую строку в / etc / sysctl.conf :

 kernel.perf_event_paranoid = 1 

Простой пример отладки

Ниже приводится игрушечная программа, которая вычисляет 2 раза 0 , 1, 2 и 3 в массив и выводит информацию:

 # include 

#define SIZE 4 void zero (char a, int size) {while (size> 0) a = 0; } void initialize (char a, int size) {ноль (a, размер); } недействительное умножение (char a, int size, int mult) {int i; для (i = 0; i аргумент? Оно должно быть 2. Ноль раз все равно нулю. Это объясняет результаты. Однако как функция main локальная переменная mult в конечном итоге равна нулю ? Он инициализируется в main и только передается в функцию вычисления. Давайте установим аппаратную точку наблюдения на mult и продолжаем обратное выполнение программы:

 (rr) вверх # 1 0x 401258 в основном (argc = 1, argv = 0x7ffe0bea5c 86) в multiply.c: 37 37 умножить (a, SIZE, mult);  (rr) watch -l mult Аппаратная точка наблюдения 4: -location mult (rr) reverse-continue Продолжение.  Аппаратная точка наблюдения 4: -location mult Старое значение = 0 Новое значение = 2 ноль (a = 0x7ffe0bea5b 64 "", size = 3) at multiply.c: 7 7 a  = 0;  
 

Ах, теперь становится ясно, как все пошло не так. Функция ноль записала после конца массива a и перезаписал mult переменная, даже если она не была не прошло. Размер - выражение должно иметь вид - размер . Мы видим вызов ноль скрыто в функции инициализировать :

 (rr) где # 0 ноль (a = 0x7ffe0bea5b 86 "", size = 3) at multiply.c: 7 # 1 0x 401184 в инициализации (a = 0x7ffe0bea5b 64 "", size = 4) at multiply.c: 19 # 2 0x 0000000000401247 в основном (argc = 1, argv = 0x7ffe0bea5c) 64) в multiply.c: 35 

Если мы хотим, мы можем использовать обычные продолжения GDB и воспроизводить его вперед и проходить те точки останова, которые мы установили снова ранее:

 (rr) c Продолжение.  Аппаратная точка наблюдения 4: -location mult Старое значение = 2 Новое значение = 0 ноль (a = 0x7ffe0bea5b 86 "", size = 3) at multiply.c: 6 6 while (size > 0) (rr) c Продолжаем.  Точка останова 3, умножение (a = 0x7ffe0bea5b 64 "", size = 4, mult = 0) at multiply.c: 25 19 для (i = 0; i

Leave a comment

Your email address will not be published. Required fields are marked *