Почему в 1С возникает ошибка о неопределенной процедуре в общем модуле и не срабатывает точка останова?

Программист 1С v8.3 (Обычные формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

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

{ОбщийМодуль.ОбщегоНазначения(4574,8)}: Процедура или функция с указанным именем не определена (ПолучитьSIDСтудента)

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

Причина: особенности компиляции модулей и препроцессор

Проанализируем механику работы платформы 1С:Предприятие в клиент-серверном режиме. Ошибка «Процедура или функция с указанным именем не определена» является ошибкой стадии компиляции, а не исключением времени выполнения (runtime exception).

  1. Момент компиляции общего модуля: общий модуль компилируется целиком при первом обращении к любому его экспортируемому методу или свойству в рамках текущего контекста исполнения. Если в модуле содержится хотя бы одна синтаксическая ошибка или неразрешенная ссылка, весь модуль не может скомпилироваться в байт-код.
  2. Почему не работают точки останова: отладчик и режим остановки по ошибке перехватывают управление только в момент выполнения скомпилированного кода. Если общий модуль падает на этапе синтаксического анализа и препроцессорной обработки, управление до точек останова физически не доходит.
  3. Конфликт контекстов и директив препроцессора: если общий модуль имеет признаки исполнения и на клиенте, и на сервере, платформа собирает для него раздельные контексты. Если процедура или функция объявлена внутри препроцессорной инструкции #Если Клиент Тогда, то при сборке серверного контекста модуль парсится без этого блока. Любой вызов данной функции из кода, выполняющегося на сервере (или из процедуры того же модуля без аналогичной директивы), приводит к ошибке компиляции.

Посмотрим на пример ошибочного кода в общем модуле:


#Если Клиент Тогда
Функция ПолучитьSIDСтудента(Студент) Экспорт
    // Клиентская логика получения идентификатора
    Возврат Идентификатор;
КонецФункции
#КонецЕсли

Процедура ОбработатьДанныеСтудента(Студент) Экспорт
    // Данная процедура доступна и на сервере, и на клиенте
    SID = ПолучитьSIDСтудента(Студент); // На сервере этой функции не существует!
КонецПроцедуры

При открытии структуры подчиненности происходит серверный вызов (например, функции проверки прав или чтения связанных документов через ПолныеПрава.ПолучитьСписокПодчиненныхДокументов). Сервер обращается к общему модулю, пытается его скомпилировать, не находит объявленную функцию в серверном контексте и выбрасывает исключение компиляции.

Способ 1. Корректировка директив препроцессора

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

  1. Открываем проблемный общий модуль в конфигураторе.
  2. Находим функцию, указанную в тексте ошибки, и анализируем обрамляющие конструкции #Если Клиент Тогда, #Если Сервер Тогда, #Если ТолстыйКлиентОбычноеПриложениеТогда.
  3. Удаляем лишние директивы препроцессора или оборачиваем вызывающий код в соответствующие условия, чтобы серверный контекст не обращался к клиентским процедурам.

// Корректное объявление без блокировки серверного контекста:
Функция ПолучитьSIDСтудента(Студент) Экспорт
    // Логика функции, доступная во всех разрешенных свойствами модуля контекстах
    Возврат Студент.УникальныйИдентификатор();
КонецФункции

Способ 2. Проверка конфигурации для быстрого поиска скрытых ошибок

Чтобы не сталкиваться с невидимыми ошибками во время работы пользователей, используем штатный механизм превентивной проверки метаданных:

  1. В главном меню Конфигуратора переходим в раздел Конфигурация → Проверка конфигурации....
  2. В появившемся окне включаем флаг Синтаксический контроль модулей.
  3. Обязательно отмечаем все целевые среды выполнения: Тонкий клиент, Толстый клиент (обычное приложение), Толстый клиент (управляемое приложение), Сервер, Внешнее соединение.
  4. Включаем флаг Проверка логической целостности конфигурации и нажимаем кнопку проверки.

Данный инструмент принудительно скомпилирует все модули конфигурации во всех доступных контекстах и выведет полный список скрытых несовместимостей с точным указанием строк.

Способ 3. Архитектурное разделение общих модулей

Для предотвращения подобных коллизий в дорабатываемых конфигурациях рекомендуется отказаться от смешивания разнородного кода с помощью директив препроцессора внутри одного модуля. Разделим функционал по специализированным модулям:

  1. Модули с суффиксом КлиентСервер: имеют флаги «Клиент» и «Сервер», содержат только универсальные алгоритмы без обращений к базе данных или элементам интерфейса.
  2. Модули с суффиксом Сервер или СерверПовтИсп: содержат логику работы с базой данных и метаданными, выполняются только на стороне сервера.
  3. Модули с суффиксом Клиент: содержат пользовательские интерфейсные обработчики и вызовы интерактивных диалогов.

Также важно помнить, что очистка локального кэша пользователя в каталогах AppData\Local\1C и AppData\Roaming\1C не устраняет проблемы серверной компиляции. При внесении масштабных изменений в общие модули в клиент-серверном режиме всегда выполняйте полное обновление конфигурации базы данных без использования динамического обновления («демонского обновления»), чтобы исключить рассинхронизацию серверного кэша метаданных.

← На главную