К статье
Практический материал

Разработка и Конфигурация · 12 мин

Стек вызовов в 1С: что это и как его использовать

Стек вызовов в 1С: что это такое, как читать последовательность вызовов процедур и функций, где смотреть стек в конфигураторе и как искать ошибки.

Стек вызовов в 1С — это последовательность процедур и функций, которые платформа выполнила, чтобы дойти до текущей точки исполнения кода. Когда одна процедура вызывает другую, та — третью, платформа запоминает весь путь: от первого обработчика события до строки, где код выполняется прямо сейчас. Этот путь и есть стек вызовов.

Практическая ценность стека вызовов раскрывается при отладке. Если программа выдала ошибку «Поле объекта не обнаружено» или «Деление на ноль», сообщение показывает только строку, где возникла проблема. Но причина часто находится выше: в процедуре, которая передала неверный параметр, или в обработчике, который вообще не должен был запуститься. Стек вызовов показывает всю цепочку, и по ней можно пройти назад к источнику.

Разобраться со стеком вызовов нужно любому, кто пишет или дорабатывает код на встроенном языке 1С: разработчикам, внедренцам, администраторам, которые анализируют ошибки пользователей. Ниже — как устроен стек, где его смотреть в конфигураторе и в технологическом журнале, как читать цепочку вызовов и какие типичные ошибки встречаются при анализе.

Как устроен стек вызовов и зачем он нужен

Стек работает по принципу «последним пришёл — первым вышел». Когда процедура А вызывает процедуру Б, платформа кладёт запись о вызове на вершину стека. Когда Б вызывает функцию В, запись о В оказывается ещё выше. После завершения В её запись снимается, и управление возвращается в Б, затем — в А. В любой момент времени стек показывает активную цепочку: кто кого вызвал и на какой строке каждый уровень сейчас находится.

В терминах платформы 1С каждый элемент стека содержит имя модуля (например, общий модуль или модуль объекта документа), имя процедуры или функции и номер строки, на которой был сделан вызов. Этого достаточно, чтобы восстановить полный путь исполнения — от обработчика события формы или подписки на событие до глубоко вложенной служебной функции.

Зачем это нужно на практике: типовая конфигурация может содержать цепочки из пяти-десяти вложенных вызовов. Обработчик «ПриЗаписи» документа вызывает процедуру проведения, та — функцию расчёта итогов из общего модуля, та — запрос и функцию обработки результата. Ошибка всплывёт в самой глубокой точке, а исправлять её часто нужно на несколько уровней выше. Без стека вызовов поиск источника превращается в ручную расстановку точек останова наугад.

Где посмотреть стек вызовов в конфигураторе

Основной инструмент — отладчик конфигуратора. Запустите отладку (меню «Отладка» — «Начать отладку» или клавиша F5), воспроизведите ситуацию и остановите выполнение в нужной точке: по точке останова, по команде «Остановить» или автоматически при возникновении ошибки, если включена остановка по ошибке (меню «Отладка» — «Остановка по ошибке»).

В момент остановки откройте окно стека вызовов: меню «Отладка» — «Стек вызовов». Появится таблица, где верхняя строка — текущая исполняемая процедура, а ниже идут все вызвавшие её уровни вплоть до начальной точки входа. Двойной щелчок по любой строке переносит в соответствующее место кода — при этом отладчик показывает значения переменных именно того уровня стека, который вы выбрали.

Порядок действий
  1. 1
    Откройте конфигуратор и запустите отладку (F5)
  2. 2
    Включите остановку по ошибке или расставьте точки останова в предполагаемой цепочке
  3. 3
    Воспроизведите ошибку в клиентском приложении
  4. 4
    При остановке откройте меню «Отладка» — «Стек вызовов»
  5. 5
    Двойным щелчком по строкам стека пройдите по уровням вверх и найдите, где в цепочку попал неверный параметр

Ещё один источник — текст сообщения об ошибке. В файловой и клиент-серверной информационной базе сообщение об ошибке исполнения обычно содержит фрагмент стека: строку «{ОбщийМодуль.ИмяМодуля.Модуль(123)}: Ошибка при вызове метода...» с указанием модуля и строки, а ниже — контекст вызвавшего кода. Этого хватает для первичной диагностики даже без запуска отладки.

Как читать стек вызовов при анализе ошибки

Читать стек следует сверху вниз. Верхняя строка — место, где произошла ошибка. Но первый вопрос при анализе — не «что сломалось здесь», а «кто и с какими данными сюда пришёл». Переходите на уровень ниже и смотрите значения аргументов, с которыми была вызвана текущая процедура. Если аргумент неверный — поднимайтесь ещё выше, к месту, где он сформирован.

Обращайте внимание на тип модуля в каждой строке. Если в цепочке присутствуют подписки на события или обработчики, которые вы не вызывали явно, — это нормально: платформа сама вставляет их в стек при записи объекта или проведении документа. Неожиданная подписка в стеке — частый признак того, что ошибку вызывает чужая доработка, а не ваш код.

Контрольные точки

Как проверить результат

Верхняя строка стека
Норма

Указывает на строку, где логично ожидать ошибку по её тексту

Тревожный признак

Строка не связана с текстом ошибки — возможно, смотрите не тот сеанс или устаревший журнал

Промежуточные уровни
Норма

Цепочка вызовов соответствует логике прикладного решения

Тревожный признак

В стеке есть неожиданные подписки, расширения или внешние обработки

Значения параметров на каждом уровне
Норма

Типы и значения соответствуют ожиданиям вызываемой процедуры

Тревожный признак

На каком-то уровне появляется Неопределено, пустая ссылка или неверный тип

Отдельный приём — сравнение стека в рабочей и проблемной ситуациях. Если одна и та же операция у одного пользователя работает, а у другого падает, снимите стек вызовов в обоих случаях и сравните. Различия в цепочке (например, срабатывание дополнительной подписки при определённых правах или настройках) быстро локализуют причину.

Стек вызовов при клиент-серверном исполнении

Особенность платформы 1С — разделение кода на клиентский и серверный контексты. Когда клиентская процедура вызывает серверную (с директивой &НаСервере), это физически отдельный вызов на сервере приложений, и единый сквозной стек «клиент → сервер» в отладчике отображается с ограничениями: серверная часть стека видна при отладке серверного кода, клиентская — при отладке клиентского.

Чтобы отлаживать серверный код в файловой базе, в параметрах запуска отладки должен быть включён соответствующий режим, а в клиент-серверном варианте на сервере 1С должен быть разрешён режим отладки (параметр -debug при запуске агента сервера). Без этого точки останова в серверных процедурах не сработают, и стек серверной части вы не увидите.

При анализе ошибок через технологический журнал или журнал регистрации учитывайте: стек в тексте ошибки отражает только тот контекст, где ошибка зафиксирована. Если сбой произошёл на сервере, клиентская часть цепочки в сообщении может отсутствовать — её придётся восстанавливать по коду формы или обработчика, который инициировал серверный вызов.

Программная работа со стеком и типовые сценарии

Во встроенном языке нет функции, которая напрямую возвращает полный стек вызовов как массив. На практике используют обходные приёмы: конструктор объекта «ИнформацияОбОшибке» в блоке Попытка...Исключение даёт описание ошибки с фрагментом стека в свойстве «ПодробноеОписаниеОшибки», а для собственного логирования разработчики передают имя вызывающей процедуры параметром или фиксируют ключевые точки в журнале регистрации.

Диагностика «лишних» вызовов при записи объекта

Классическая ситуация: при записи документа ошибка возникает в неожиданном месте. Открываете стек и видите, что между вашим обработчиком и точкой ошибки находятся две подписки на события и вызов из расширения конфигурации. Вывод — сначала отключить расширение и проверить, исчезла ли ошибка, затем поочерёдно анализировать подписки. Стек здесь работает как карта: он показывает всех участников процесса, включая тех, о которых вы не знали.

Поиск источника рекурсии

Ошибка «Переполнение стека» (stack overflow) возникает, когда процедура прямо или косвенно вызывает саму себя без условия выхода. В этом случае стек вызовов в момент остановки состоит из многократно повторяющейся одной и той же цепочки. Достаточно посмотреть на повторяющийся фрагмент из двух-трёх процедур — в нём и находится циклический вызов, который нужно разорвать условием или переписать итеративно.

Типичные ошибки
01
Анализ только верхней строки стека: исправляется симптом в точке падения, а причина — неверный параметр уровнем выше — остаётся
02
Игнорирование подписок на события и расширений в стеке: чужой код в цепочке принимается за «системный» и не проверяется
03
Отладка серверного кода без включённого режима отладки на сервере: точки останова не срабатывают, стек кажется пустым
04
Поиск ошибки по устаревшему тексту из журнала регистрации: стек и строки уже не соответствуют текущей версии кода

Ограничения и альтернативные инструменты

Стек вызовов показывает путь исполнения, но не показывает историю изменения данных. Если проблема в том, что переменная получила неверное значение задолго до текущего вызова, стек не поможет — нужны точки останова с условиями, табло (вычисление выражений) и пошаговое исполнение. Стек и трассировка дополняют друг друга.

Второе ограничение — производительный код и фоновые задания. Стек фонового задания виден только при подключении отладчика к соответствующему сеансу (в окне отладки — список предметов отладки). Если фоновое задание завершилось с ошибкой до подключения, ориентируйтесь на текст ошибки в журнале регистрации и консоли заданий.

Маршрут решения

Как выбрать действие

Ошибка воспроизводится на тестовой базеЗапустите отладку в конфигураторе и анализируйте стек вызовов в момент остановки
Ошибка только у пользователя на рабочей базеВозьмите фрагмент стека из текста сообщения об ошибке и журнала регистрации, воспроизведите на копии
Ошибка в фоновом заданииПодключите отладку к сеансу фонового задания или проанализируйте текст ошибки в регистрации
Переполнение стекаНайдите в стеке повторяющуюся цепочку процедур и разорвите рекурсию условием выхода

Для массового сбора диагностики в клиент-серверных системах дополнительно применяют технологический журнал (настраивается через logcfg.xml): события EXCP фиксируют исключения с контекстом. Это тяжелее в настройке, чем обычная отладка, но работает без остановки системы и подходит для «плавающих» ошибок, которые нельзя воспроизвести по команде.

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

Частые вопросы о стеке вызовов в 1С

Чем стек вызовов отличается от трассировки кода?

Трассировка — это пошаговое исполнение с просмотром каждой строки по порядку. Стек вызовов — моментальный снимок цепочки вложенных вызовов в конкретной точке. Трассировка показывает, что происходило во времени, стек — как программа пришла в текущее состояние.

Почему в стеке вызовов нет процедуры, которая точно выполнялась?

Стек содержит только активные (незавершённые) вызовы. Если процедура отработала и вернула управление, её запись снята со стека. Также проверьте, не выполняется ли нужный код в другом контексте — на сервере или в фоновом задании, к которому отладчик не подключён.

Как понять, какая строка в стеке — мой код, а какая — типовой конфигурации?

Ориентируйтесь на имена модулей и процедур: доработки обычно находятся в расширениях, добавленных общих модулях или переопределённых обработчиках с узнаваемыми префиксами. Типовые модули имеют стандартные имена из поставки конфигурации. Сомнительную строку откройте двойным щелчком и посмотрите сам код.

Можно ли получить стек вызовов программно и записать в лог?

Готовой функции полного стека во встроенном языке нет. В блоке Попытка...Исключение используйте ИнформацияОбОшибке() — свойство ПодробноеОписаниеОшибки содержит описание с фрагментом контекста вызовов. Для полноценного логирования цепочки разработчики передают имя вызывающей процедуры параметром или пишут ключевые точки в журнал регистрации.

Ошибка «Переполнение стека» — это нехватка памяти?

Нет, почти всегда это бесконечная рекурсия: процедура прямо или через цепочку других вызовов вызывает саму себя без условия завершения. Откройте стек в момент ошибки — повторяющийся фрагмент цепочки укажет на циклический вызов. Лечится добавлением условия выхода или заменой рекурсии циклом.

Виден ли стек вызовов в журнале регистрации?

Журнал регистрации фиксирует событие ошибки с её текстом, который обычно включает модуль, строку и фрагмент контекста вызова, но не полный многоуровневый стек. Для глубокого анализа цепочки потребуется отладка на копии базы или настройка технологического журнала.

Итог

Что важно запомнить

Стек вызовов — это цепочка процедур от точки входа до текущей строки исполнения. Смотрите его в конфигураторе через «Отладка — Стек вызовов», читайте сверху вниз и ищите уровень, где в цепочку попал неверный параметр. Учитывайте разделение клиентского и серверного контекстов, подписки на события и расширения — они тоже отображаются в стеке и часто оказываются источником ошибки.