Отладка скриптов вообще дело крайне нужное и полезное. Кроме основной задачи — поиска и удаления ошибок, отладка прямо улучшает качество и работоспособность программы в целом. Выловленные баги, исправленная логика — все это делает программу стабильнее в работе, что весьма желанная цель при ее написании. Все ниженаписанное основывается на моем опыте, так что воспринимайте это как мое имхо ))
Итак, какие бывают ошибки и как их можно отловить.
1. Самые простые и самые распространённые — это ошибки, связанные с чудным свойством php — динамической типизацией. Помимо того, что иногда просто упускаешь из виду, что там и в каком формате у тебя хранится, php сам подкидывает сюрпризы вида true при сравнении «qwerty» == 0 и другие чудеса автоматического приведения типов и подобные им брейнфаки.
Если точно известно место, где переменная перестает себя вести, как от нее ожидают, то я особо не мудрствую и ставлю var_dump(переменная). Если догадка подтверждается, то исправляем косяк и идем дальше.
Но не всегда получается определить точное место расхождения значения с ожидаемым. Расхождение это может быть зарыто глубоко в дебри кода, либо наоборот, находится на самом видном месте.
Так же бывает, что переменная меняет значение из-за нарушенной логики приложения. Например, присвоение идет внутри локальной видимости вложенной функции или неверно построенного цикла. Наружу передается не тот результат, который ждешь, хотя с виду все правильно. Просто не там открыл или закрыл скобку и все изменяется причудливым образом.
Такую красоту довольно трудно отловить руками, особенно в крупных приложениях. Поэтому лучше воспользоваться дебаггером. Во всяких умных книжках довольно часто пишут про APD, хвалят его, но дата его последнего релиза за 2004 год как-то меня настораживает. В багтрекере пишут, что под 5.3 не хочет он работать, у меня из груши не встал, поэтому я забил на него.
Трассировку скрипта можно сделать xdebug’ом. Он часто бывает установлен, но как модуль PHP, а для нормальной работы нужно, чтобы он стоял как Zend module. По установке все итак расписано в нете, не буду повторяться.
Xdebug генерирует отчет, который показвает последовательно, кто, куда, зачем обратился. Есть специальные парсилки логов, но мне удобнее читать сырые отчеты, потому как в консоли особо красоту не получишь, а через веб я не умею отлаживать. Выдается вот такая красота:
3 67 0 0.013521 394468 drXdebugTraceFileParser->parseLine 1 /home/alex/tmp/trace.php 123 1 $line = '2\t3\t1\t0.000772\t328656\n' 4 68 0 0.013588 394584 explode 0 /home/alex/tmp/trace.php 149 2 '\t' '2\t3\t1\t0.000772\t328656\n' 4 68 1 0.013630 395376 4 69 0 0.013666 395348 count 0 /home/alex/tmp/trace.php 150 1 array (0 => '2', 1 => '3', 2 => '1', 3 => '0.000772', 4 => '328656\n') 4 69 1 0.013716 395348 4 70 0 0.013757 395436 array_pop 0 /home/alex/tmp/trace.php 178 1 array (0 => '{main}', 1 => 'ini_set') 4 70 1 0.013800 395408 4 71 0 0.013823 395332 drXdebugTraceFileParser->addToFunction 1 /home/alex/tmp/trace.php 180 5 $function = 'ini_set' $time = 4.3E-5 $memory = 236 $nestedTime = 0 $nestedMemory = 0 5 72 0 0.013900 395376 in_array 0 /home/alex/tmp/trace.php 194
Этого достаточно, чтобы проследить логику хода выполнения и отследить косяки. Забыл еще сказать, что xdebug можно подключать на лету. Обычно я выключаю и дебаггер и профайлер в php.ini, а в нужном скрипте просто включаю их вместе или по очереди через
ini_set('xdebug.default_enable', 1); ini_set('xdebug.profiler_enable', 1);
Это быстро, не нужно никаких дополнительных телодвижений. Xdebug еще можно подключать на кучу разных IDE, даже вроде в денвере он есть.Таким нехитрым образом можно отловить большинство ошибок и невнимательностей в коде. Естественно, что изначально задуманную кривую логику так не исправить.
2. Второй тип ошибок гораздо сложнее отловить. Они также появляются вследствии зевков и невнимательностей, но проявляют себя не сразу, а по наступлению определенных условий. Например, время работы или количество итераций или появление определенного числа в арифметических операциях или наоборот, его непоявление.Еще ошибки могут возникать из-за изменений среды окружения, например форк апача завершил свою сессию и скинул скрипт или крон запускает что-то, что отъело всю память и скрипт просто не может запуститься.
Таких условий может быть множество, всех их обьеденяет одна черта — они не проявляются сразу при запуске, поэтому при анализе лога дебаггера ничего подозрительного выявить нельзя.
Тут приходит на помощь замечательная утилита — strace. Я одно время мучился с тем, что апач раз в 24 часа убивал свои потоки, а с ними и скрипты, из-под которых они были запущены. Так вот был настроен сервер. Нашли ошибку, когда подключились с другого терминала непосредственно к скрипту и слушали его через strace. Там и увидели, что скрипт ловит SIGTERM. Как использовать strace я уже писал. Позволяет исследовать реальную работу скрипта в реальном времени и видит все, что с ним происходит. Вывод можно перенаправить в файл и потом проанализировать. Еще есть схожая утилита, называет ptrace. Все они родные для nix систем. Некоторые чуваки с хабры используют для схожих целей сишный дебаггер. Кому в чем удобней…
3. Третий тип ошибок заключается в том, что память начинает резко утекать куда-то и нужно выяснить куда. Они также возникают из-за невнимательности или усталости и получаются чудеса типа файл инклюдится в бесконечном цикле или переменная набирает и набирает обьемиз-за того, что ее не обнулили предварительно. Все это конечно можно отловить и через strace, но лучше использовать для этого профайлер xdebug’а.
Также этот способ следует использовать в целях профилактики, чтобы держать под контролем количество вызовов, открытий файлов и размеров переменных. Сам xdebug конечно не отдает все в удобноваримом виде, но под чтение его отчетов есть куча утилит. Я пользуюсь этим скриптом. Он выдает отчеты вида
function #calls time memory time memory ------------------------------------------------------------ ini_set 3 0.0002 584 0.0002 584 fix_string 1 0.0010 264 0.0009 184 xdebug_call_file 1 0.0001 48 0.0001 48 xdebug_call_function 1 0.0000 32 0.0000 32 var_dump 1 0.0002 0 0.0002 0 xdebug_memory_usage 1 0.0000 0 0.0000 0 xdebug_call_line 1 0.0000 0 0.0000 0 {main} 1 0.0018 480 0.0003 -368
Здесь уже можно отследить и вызовы и время. Запускаю его обычно в конце работы, чтобы посмотреть, не напортачил ли я чего в коде. Также использую его при оптимизации для оценки результатов
Вот такие нехитрые способы, надеюсь, помогут спасти время и нервы при отладке скриптов. Если есть у кого свои методики — велкам в коменты, буду рад услышать.
P.S. Если кто знает, как завести APD под 5.3, отпишитесь плз!
P.P.S Тут вот чувак просто тру-самурай, целый квест прошел чтобы найти ошибку. Шрифт жесть.
Там строку 967 в файле php_apd.c надо закоментить и все заработает.
И чтобы сделать читалку логов, надо скомпиленную pprofp скопировать в /usr/bin и создать ссылку на php в /usr/local/bin/
18 комментариев
а что за зверь KCachegrind?
var_dump одна из самых классных функций, на джаве постоянно ищут аналог)
dbaik, Kcachegrind — это интерфейс для программы Cachegrind, используемой для профилирования работы программ.
Действительно, весьма полезная функция!
strace наше все, очень удобно.
А мне вот очень интересно, как вы сделали Insert More с условием нажать на твит или g+
Плагином wp viral attack
Сам стал жертвой динамической типизацией по своей невнимательности. Спасибо за полезне советы!
APD… дата его последнего релиза за 2004 год как-то меня настораживает..
Я бы и не стал связываться — поискал бы что-то анологичное
Написав свою первую CMS, не слишком функциональную, но по особому добротную и уютную для себя, в процессе работы понял, что отладка PHP скриптов необходимый атрибут качественной работы системы в целом. Для знакомого, клепающего проги с использованием PHP отладка является основной работой в процессе производства. Говорит, заказчику нужна безупречность…
Это такая тема… отладка PHP, у меня бывает волосы начинают потеть… И говорить не хочется, а методы отличные.
Многие современные IDE поддерживают Xdebug. И выводят логи в приятном и удобном виде. Напримет нетбинс.
Я постоянно из-за невнимательности касячу. Всегда, вообще всегда использую Strace, чего и всем советую, потому что положиться только на человеческий фактор нельзя.
Уважаемые,
я, к сожалению, ни разу не програмист. Просто хобби такое есть — делать небольшие сайтики, но на CMS Joomla, типа как в конструкторе… Так вот, понадобилось в одном php скрипте поменять местами какртинки и текст. Сам я, естствнно, недодумкаю. Может кто-нибуть согласится помочь? Я так думаю, что для специалиста — это минутное дело. Чем могу — тоже помогу при необходимости. Так что если интересно — свистните пжлста на почту dimm.torok( )hotmail.com . Заранее благодарен!
Кто откликнулся — спасибо! Разобрался, всё получилось как хотел. Всем удачи во всех начинаниях!
Это конечно дурацкая заметка и видимо не понимаю на что указываю, но…
Профилирование включается одной строкой, а не двумя
ini_set(‘xdebug.profiler_enable’, 1);
(тестил на OpenServer-e >>> создает cachegrind.out.[название_скрипта] в папке e:\OpenServer\userdata\temp\xdebug\)
зачем тогда включать в скрипте / php.ini
ini_set(‘xdebug.default_enable’, 1);
если и так все прекрасно работает
Наверно потому, что чтобы включить профайлер, надо включить сам xdebug, не?
Насчет удобоворимого восприятия лог информации xdebug-а в том же OpenServer (веб-сервер — альтернатива Denwer) есть PHP профайлер в Дополнительно. Жмем на него — прогрузит в браузере Webgrind — ставим 100%, кликаем на Auto (newest) — выбираем нужное исполнение скрипта.