Когда я отлаживаю что-то, что идет не так внутри цикла, скажем, на 600-й итерации, может быть мучительно ломать каждую из них. Поэтому я попытался установить условную точку останова, чтобы прерываться только в том случае, если я = 600. Это работает, но теперь для достижения этой точки требуется почти целая минута, тогда как раньше это было почти мгновенно. Что происходит, и есть ли способ это исправить?
Почему условные точки останова так сильно замедляют мою программу?
Ответы (6)
Когда вы достигаете точки останова, Windows останавливает процесс и уведомляет об этом отладчик. Он должен переключать контексты, оценивать условие, решать, что нет, вы не хотите получать уведомления об этом, перезапускать процесс и переключаться обратно. Это может занять много циклов процессора. Если вы делаете это в тесном цикле, это займет на пару порядков больше циклов процессора, чем одна итерация цикла.
Если вы хотите немного повозиться со своим кодом, есть способ сделать условные точки останова без всех этих накладных расходов.
if <condition here> then
asm int 3 end;
Это простая инструкция по сборке, которая вручную отправляет ОС уведомление о точке останова. Теперь вы можете оценить свое состояние внутри программы, не переключая контексты. Просто не забудьте вынуть его снова, когда закончите с ним. Если int 3 сработает внутри программы, которая не подключена к отладчику, это вызовет исключение.
Это замедляет его, потому что каждый раз, когда вы достигаете этой точки, он должен проверять ваше состояние.
Что я обычно делаю, так это временно создаю другую переменную, подобную этой (в C, но это должно быть выполнимо в Delphi).
int xyzzynum = 600;
while (true) {
doSomething();
if (--xyzzynum == 0)
xyzzynum = xyzzynum;
}
затем я ставлю безусловную точку останова на строку "xyzzynum = xyzzynum;"
.
Программа работает на полной скорости, пока не пройдет цикл 600 раз, потому что отладчик просто выполняет обычное прерывание от точки останова, а не проверяет каждый раз условия.
Вы можете сделать условие настолько сложным, насколько хотите.
В дополнение к ответу Мейсона вы можете компилировать сборку int 3 только в том случае, если программа построена с определенным условием отладки:
{$ifdef debug}
{$message warn 'debug breakpoint present in code'}
if <condition here> then
asm int 3 end;
{$endif}
Итак, когда вы отлаживаете в ide, у вас есть условие отладки в параметрах проекта. Когда вы создаете конечный продукт для своих клиентов (со своим скриптом сборки?), вы не включаете этот символ, поэтому он не будет скомпилирован.
Я также включил директиву компилятора $message, поэтому при компиляции вы увидите предупреждение о том, что код все еще существует. Если вы сделаете это везде, где используете int 3, у вас будет хороший список мест, по которым вы можете дважды щелкнуть, чтобы перейти прямо к оскорбительному коду.
N@
Объяснения Мэйсона довольно хороши.
Его код можно сделать немного более безопасным, протестировав его под отладчиком:
if (DebugHook <> 0) and <your specific condition here> then
asm int 3 end;
Это ничего не сделает, когда приложение работает нормально, и остановится, если оно работает под отладчиком (независимо от того, запущено ли оно из IDE или подключено к отладчику).
А с логическим ярлыком <your specific condition here>
даже не будет оцениваться, если вы' не под отладчиком.
Условные точки останова в любом отладчике (я только предполагаю здесь) требуют, чтобы процесс каждый раз переключался между вашей программой и отладчиком каждый раз, когда срабатывала точка останова. Этот процесс занимает много времени, но я не думаю, что вы можете что-то сделать.
Обычно точки останова по условию работают, вставляя в код соответствующую инструкцию останова, а затем проверяя указанные вами условия. Он будет проверять на каждой итерации, и вполне возможно, что способ реализации проверки является причиной задержки, поскольку маловероятно, что отладчик скомпилирует и вставит полный код проверки и точки останова в существующий код.
Способ, которым вы могли бы ускорить это, заключается в том, что вы помещаете условие, за которым следует операция без побочного эффекта, непосредственно в код и прерываете эту операцию. Просто не забудьте удалить условие и операцию, когда закончите.