Регистрация | Войти
Lisp — программируемый язык программирования

Оригинальная публикация: https://gist.github.com/659495#file_sbcl_debugging_notes.txt

Перевод: http://bredogen.blogspot.com/2010/12/sbcl-slime.html

Замечания по отладке в SBCL и Slime

0. Умение сокращать размеры тестового набора - это важный навык, не зависящий от языка или инструментария. Это целое искусство - сокращать до премлемых размеров количество примеров, приводящих к появлению ошибок, неверных результатов (например, моменты, связанные с указанием полного пути или текущей директории, выполнением кода в Slime или вне него). С одной стороны, чем меньше тестовых примеров, тем лучше, но здесь надо соблюдать осторожность. Если вы в состоянии распознать баг за пару минут каким-либо другим методом, очевидно, глупо тратить несколько часов на сжатие тестового набора. Однако, если другими методами вы не в состоянии этого сделать, придется смириться с временными затратами.

1. Осторожное программирование. Речь не только о том, как избегать ошибок в коде, но и о том, как делать его легкоотлаживаемым. Избегайте IGNORE-ERRORS, не позволяйте компилятору безмолвно проглатывать ошибки. Иногда это может быть полезным, но чем больше таких мест в коде, тем сложнее использовать *BREAK-ON-SIGNALS*. Избегайте SAFETY 0 как чумы - он скроет множество огрехов. Не используйте DEBUG 0 - от этого вы не получите выгоды. Определяйте PRINT-OBJECT методы для собственных объектов, давайте им имена. Никогда не употребляйте INTERRUPT-THREAD или WITH-TIMEOUT, пока вы не будете точно уверены в том, что делаете, и пока не поймете, почему их лучше не использовать.

2. Не задумывайтесь. Просто внимательно вчитывайтесь в сообщения об ошибках. Иногда они бесполезны, но иногда вы рискуете упустить много полезной информации.

3. Изучайте возможности инструментария. Здесь стоит остановиться подробнее.

3.0 M-. - это отличная вещь. Нажимая 'v' в отладочном окне Slime, вы также попадаете в участки кода, предоставляющего достаточно много информации для отладки, но M-. можно использовать везде.

3.1 Slime Inspector - один из первых главных отладочных инструментов. Познакомьтесь с его возможностями, они того стоят.

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

3.3 Разберитесь с *BREAK-ON-SIGNALS* и TRACE. Не забывайте, что SBCL предоставляет некоторые расширения возможностей TRACE.

3.4 Пошаговое выполнение по сути не является отладочным инструментом. Я считаю, что это всего лишь средство наблюдения за ходом исполнения. Иногда это может быть полезным в отладке, но только при компиляции кода с DEBUG 3, когда (STEP (FOO)) доставит вас в нужное место.

3.5 Пользуйтесь M-RET (macroexpand) в Slime. Попробуйте (SETF *PRINT-GENSYM* NIL) и посмотрите, что будет происходить. Это несет с собой потенциальные опасности, но зато может позволить легко копировать и вставлять код, в который раскрывается ваш тестовый пример. (Замена раскрытий макросов в пакете COMMON-LISP, как правило, нецелесообразно, но в других пакетах может быть очень полезным.)

3.6 Если ничего не помогло, попробуйте (sb-ext:restrict-compiler-policy 'safety 3) и (sb-ext:restrict-compiler-policy 'debug 3), после чего перекомпилируйте весь код. Теперь отладка станет легче. Если ошибка исчезла, либо (а) вы ошиблись с типами (или допустили похожую ошибку) в коде, собранном с SAFETY 0, и она не терялась благодаря IGNORE-ERRORS или HANDLER-CASE, либо (б) вы обнаружили баг в SBCL: вообще говоря, политика компилятора не должна изменять поведение кода, за исключением нескольких допускаемых ANSI случаев при использовании SAFETY 3, или же высокий уровень отладки препятствует оптимизации хвостовой рекурсии. Знающие Scheme объяснят вам, что это может иметь значение.

3.7 DISASSEMBLE не есть штатное средство отладки, но иногда может быть полезным. Это зависит от сути имеющейся проблемы.

4. Расширения отладочной печати. Часто это простейшее средство, которым можно воспользоваться. Не стыдитесь этого.

4.1 Днамические переменные могут быть полезны

(LET ((*DEBUG* :MAGIC)) ...) и, где-либо в коде,
(WHEN (EQ :MAGIC *DEBUG*) (PRINT (LIST :FOO FOO)))

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

4.2 Не бойтесь вставлять в отлаживаемый код (break "foo=~S" foo) или подобные вызовы.

4.3. SB-DEBUG:BACKTRACE все же можно использовать.

@2009-2013 lisper.ru