1C-Code → Основы 1С → Отладка: как искать причину
Навык, который отличает того, кто чинит за десять минут, от того, кто чинит за день. Точки останова, замер и порядок поиска.
Глава 36 из 36 · чтение примерно 22 минут
Задача «не считается скидка» решается не знанием языка, а умением найти место, где всё пошло не так.
Начинающий читает код глазами и гадает. Опытный ставит точку останова и смотрит. Разница во времени — десятки раз.
1. Повторить. Пока ошибка не воспроизводится по шагам, чинить нечего: вы не узнаете, починили ли. Первый вопрос пользователю — «что вы нажали».
2. Сузить. Не «не работает отчёт», а «не работает на этом складе за этот месяц». Каждое уточнение выбрасывает половину кода из подозреваемых.
3. Найти место. Точка останова, а не чтение глазами.
4. Понять, а потом чинить. Правка, сделанная до понимания, лечит симптом и оставляет причину.
Отладчик конфигуратора останавливает выполнение на нужной строке и показывает значения всех переменных.
Условная точка останова — срабатывает, только когда условие истинно. В цикле по тысяче строк это единственный способ добраться до нужной, не нажимая «продолжить» тысячу раз.
Отладка фоновых заданий и сервера включается отдельно в настройках сервера и конфигуратора. Пока не включена, точки в серверном коде не срабатывают — и это первая причина недоумения «почему не останавливается».
Когда отладчик не поможет
Ошибка у пользователя на боевой базе, воспроизвести нельзя, отладку включать нельзя. Тогда остаётся журнал регистрации: ЗаписьЖурналаРегистрации с понятным комментарием в подозрительных местах.
Это не признак слабости, а нормальный способ: половина разбирательств на настоящих базах идёт именно так. Важно потом убрать временные записи — журнал не свалка.
Отдельный инструмент конфигуратора: показывает, сколько заняла каждая строка и сколько раз выполнилась.
Смотреть надо на число вызовов, а не на суммарное время: строка, выполнившаяся тысячу раз по три миллисекунды, и есть виновник трёх секунд. Про это была глава «Что тормозит».
На чём спотыкаются
Чинят, не поняв. Добавили проверку — ошибка исчезла. Через месяц вернулась в другом месте, потому что причина осталась.
Меняют несколько вещей сразу. Стало работать — непонятно от чего. Меняют по одному.
Не проверяют, что ошибка действительно ушла. Проверяют тем же способом, которым воспроизводили, а не «вроде теперь нормально».
Оставляют отладочные Сообщить в рабочем коде. Пользователь видит служебные строки и перестаёт доверять программе.
Упражнение 1. Сузить круг
Функция ЧтоДальше(Повторяется, МестоНайдено) подсказывает следующий шаг поиска: если ошибка не повторяется — «Воспроизвести»; если повторяется, но место не найдено — «ТочкаОстанова»; если место найдено — «Понять».
Решается в тренажёре: код запускается и проверяется сразу.
Точка останова — только начало. Полезного в отладчике четыре вещи, и новички обычно пользуются одной.
Табло — окно, куда выписывают выражения, за которыми следят. Не только переменные: туда пишут Строки.Количество(), Сумма / Количество, любое выражение — и видят его значение на каждом шаге.
Вычислить выражение — посчитать что-нибудь прямо сейчас, в текущем состоянии. Здесь же разворачивают коллекции: таблицу значений можно раскрыть и посмотреть строки, а не догадываться, что в ней.
Стек вызовов — список «кто кого вызвал», от текущей строки вверх.
Пошаговое выполнение — идти по коду и смотреть, куда он на самом деле сворачивает.
| Действие | Что делает | Когда нужно |
|---|---|---|
| Точка останова | остановиться на этой строке | знаете место, хотите посмотреть значения |
| Шагнуть через | выполнить строку целиком и встать на следующую | вызов доверяем, интересно, что дальше |
| Шагнуть в | войти внутрь вызванной процедуры | подозрение, что ошибка внутри вызова |
| Выйти из процедуры | доработать текущую и вернуться к вызвавшей | вошли по ошибке или уже всё увидели |
| Продолжить | бежать до следующей точки останова | здесь всё понятно, интересно следующее место |
| Остановить | прервать выполнение | увидели причину, дальше не надо |
Стек вызовов отвечает на «кто это вызвал»
Вы стоите внутри функции, у неё в параметрах ерунда. Вопрос не «что тут не так», а «откуда это пришло».
Стек вызовов показывает всю цепочку: ваша функция, та, что её вызвала, и так до самого начала — до нажатия кнопки или до начала проведения. По каждой строке цепочки можно щёлкнуть и увидеть значения переменных ТАМ.
Это способ за минуту понять то, на что чтением кода уходит полдня: типовая конфигурация большая, и путей до одной процедуры обычно несколько.
Почему точка останова не срабатывает
Проверяйте по порядку, причин ровно пять:
1. Код выполняется на сервере, а отладка сервера не включена. Включается в самом сервере (параметр отладки) и в конфигураторе — «Отладка разрешена».
2. Это фоновое задание. Оно тоже сервер, и ему нужна отдельная галочка «Отлаживать фоновые задания» — иначе оно просто пробежит мимо ваших точек.
3. Строка вообще не выполняется. Условие выше не сработало, и до неё не доходит — это уже находка, а не проблема отладчика.
4. Выполняется другой код: расширение, копия обработки, другая база. Самая обидная причина.
5. Точка стоит на строке, которой в откомпилированном коде нет — на комментарии или на пустой строке.
Есть процедура на триста строк, и результат в конце неверный. Ставить точку на каждой строке — день работы.
Приём простой: поставить точку ровно посередине и посмотреть, правильны ли данные там. Если правильны — ошибка во второй половине, если нет — в первой. Повторить с половиной половины.
Триста строк разбираются семью такими шагами. То же работает не только с кодом: так же ищут «какая из двадцати строк файла ломает загрузку» и «какое из пятидесяти изменений сломало отчёт».
Упражнение 2. Починить деление на ноль
Функция Средние(Списки) считает среднюю цену по каждому списку и склеивает ответы через запятую. На пустом списке она падает. Почините СредняяЦена так, чтобы для пустого списка получался 0. Ожидаемый ответ — «200, 0, 50».
Решается в тренажёре: код запускается и проверяется сразу.
Разработчик не может повторить ошибку пользователя. Код тот же. Значит, отличается не код, и перебирать надо короткий список:
Данные. У него в документе строка без склада, отрицательное количество, дата 2099 года. Самая частая причина из всех.
Права. Под полными правами видно всё, под правами кладовщика — не всё. Запрос возвращает меньше строк, а код этого не ждал.
Настройки. Учётная политика, функциональные опции, настройки пользователя. Половина кода в типовых ведёт себя по-разному в зависимости от них.
Версия и кэш. У него старая версия конфигурации или не почищенный кэш клиента.
Первый практический шаг — не читать код, а попросить документ, на котором ломается, и проверить на нём.
Отладка запросов — отдельное умение
Запрос не отлаживается по шагам: он либо выполнился, либо нет. Поэтому разбирают его иначе.
Останавливаются на строке Запрос.Выполнить(), через «Вычислить выражение» смотрят Запрос.Текст и копируют его в консоль запросов. Там же ставят параметры — их значения тоже видны в отладчике — и гоняют запрос, отрезая по одному условию, пока не станет ясно, какое из них убивает строки.
Чаще всего виноваты три вещи: соединение, размножившее строки; условие на поле, где NULL; и виртуальная таблица с параметрами, заданными не там. Про все три была часть «Данные».
Упражнение 3. Ошибка на единицу
Функция Последний(Массив) должна возвращать последний элемент, а падает с «индекс за границами». Найдите причину и почините. Проверка передаёт Гвозди, Шурупы, Молоток.
Решается в тренажёре: код запускается и проверяется сразу.
Правка без проверки — половина работы, и обычно худшая половина: вторая ошибка, внесённая при починке первой, обнаруживается уже у пользователя.
Проверять тем же способом, которым воспроизводили. Не «вроде теперь нормально», а те же шаги, тот же документ, тот же период.
Проверить, что не сломали соседнее. Правка в общей функции задевает всех, кто её вызывает. Кто вызывает — показывает глобальный поиск по конфигурации, и смотреть туда надо до правки, а не после.
Проверить границы. Починили на трёх строках — попробуйте на нуле строк и на одной. Именно там живут деления на ноль и ошибки на единицу, которые вы только что чинили.
Когда замер полезнее отладчика
Отладчик отвечает на «почему неправильно». На «почему долго» он не отвечает: под отладкой всё медленно, и разницы не видно.
Для скорости есть замер производительности в конфигураторе, а для боевого сервера, где отладка запрещена, — технологический журнал: он пишет, какие запросы выполнялись, сколько заняли и какие блокировки ждали. Настраивается файлом logcfg.xml на сервере.
Знать про него полезно и на собеседовании: вопрос «как искать тормоза на боевой базе» задают часто, и правильный ответ начинается не с отладчика.
Повторить, сузить, найти место, понять, починить, проверить тем же способом. Точка останова вместо чтения глазами; условная — когда строк тысячи. Отладку сервера и фоновых включают отдельно, иначе точки не срабатывают. Где отладчика нет — журнал регистрации, и временные записи потом убирают. В замере смотрят на число вызовов, а не на общее время.
Читать про код и писать код — разные умения. В тренажёре к этой главе идут упражнения: вы пишете решение, оно запускается на настоящем интерпретаторе 1С и проверяется сразу, без установки платформы.