#gdb #lldb
Вопрос:
У меня есть две точки останова A
и B
. И я хотел бы подсчитать, сколько случаев A
произойдет до B
того, как будет нанесен удар. Дело в том, что это A
происходит довольно часто (>1000), поэтому я не могу вручную продолжать и повторять. A
также может произойти после B
, поэтому я не могу запустить программу до завершения, чтобы узнать количество попаданий. Есть ли автоматический способ сделать это?
Ответ №1:
Вы можете сделать это довольно легко с помощью точки останова автоматического продолжения в точке A и команд в точке останова B. В простейшем подходе точка останова на A будет выглядеть так:
break set <HoweverYouSpecifyA> --auto-continue 1 -N BreakpointA
Тогда точка останова на B будет:
break set <HoweverYouSpecifyB> -C "break list BreakpointA" -C "break disable BreakpointA" --one-shot
На break list BreakpointA
выходе будет показано количество попаданий A, когда вы нажмете B, что вы и хотели знать. Отключив A, когда вы нажмете B, количество попаданий для A останется таким же, каким оно было, когда вы нажмете B, поэтому вы сможете проверить его в любой момент после этого (до повторного запуска).
Мне нравится использовать именованные точки останова, когда я делаю небольшую двухэтапную точку останова, подобную этой, в противном случае вам придется использовать идентификатор первой точки останова, и он может меняться от запуска к запуску в зависимости от порядка, в котором вы устанавливаете точки останова.
Я также сделал точку останова B одноразовой, так как вы просто используете ее, чтобы заморозить количество попаданий A, поэтому ей нужно попасть только один раз. Если это более удобно, вы также можете заставить B автоматически продолжить, а затем просто считывать количество попаданий A при выходе из программы.
Если бы вы хотели стать более модным, вы могли бы вместо этого использовать обратный вызов Python для B, получить количество попаданий от A и сообщить об этом так, как вы хотите. Это больше работы, но легче управлять форматированием вывода с Python…
Ответ №2:
Есть ли автоматический способ сделать это?
В GDB я обычно делаю это:
(gdb) ign 1 10000
(gdb) cont
Когда будет достигнута вторая (B) точка останова, info break
скажет что-то вроде:
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000555555555129 in a at t.c:1
breakpoint already hit 1234 times <<<===
ignore next 8766 hits
2 breakpoint keep y 0x0000555555555130 in b at t.c:2
breakpoint already hit 1 time
Если 10000 окажется недостаточно, вы всегда можете увеличить его до 10000000 вместо этого.
Комментарии:
1. Не можете ли вы сделать то же самое, добавив команду «продолжить» к первой точке останова? Таким образом, вам не придется угадывать максимальное количество попаданий.
2. @JimIngham, Вы могли бы, но это, скорее всего, медленнее (хотя я не измерял это). С
ignore
помощью GDB не нужно оценивать вложенную команду.3. Если gdb сможет справиться с остановкой достаточно быстро, чтобы одна команда «продолжить» поднялась над шумом, я был бы либо сильно впечатлен ее эффективностью (или, к сожалению, разочарован производительностью интерпретатора команд). Тем не менее, прошло несколько десятилетий с тех пор, как я в последний раз работал над gdb, поэтому в наши дни я не очень хорошо понимаю его производительность.