Почему 1С аварийно завершает работу при закрытии формы и как устранить ошибку в модуле fmtd.dll?

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

При работе в управляемом интерфейсе разработчики и пользователи иногда сталкиваются с внезапным падением программы: окно тонкого клиента закрывается с ошибкой операционной системы APPCRASH исполняемого файла 1CV8C.exe, где в качестве сбойного модуля указывается библиотека fmtd.dll. Особенность ситуации заключается в том, что в конфигураторе через стандартный отладчик поймать точку сбоя невозможно, так как ошибка происходит на уровне нативного кода платформы уже после завершения всех обработчиков встроенного языка.

Разберем природу этого поведения, выясним причину сбоя и рассмотрим проверенные практические способы обхода и устранения данной ошибки.

Анализ механизма сбоя и причин падения клиента

Библиотека fmtd.dll входит в состав платформы 1С:Предприятие и отвечает за рендеринг, форматирование и обработку графического элемента Форматированный документ (ФорматированныйДокумент).

Проанализируем цепочку событий, приводящую к аварийному завершению:

  1. В управляемых формах 1С для оптимизации быстродействия и потребления памяти используется механизм отложенной отрисовки элементов интерфейса (ленивая инициализация). Если элемент расположен на неактивной вкладке группы страниц, его внутренний графический контекст не создается до тех пор, пока пользователь физически не переключится на эту страницу.
  2. Если реквизит типа ФорматированныйДокумент и соответствующее поле формы создаются программно (через вызовы ИзменитьРеквизиты и Элементы.Добавить) на неактивной закладке, платформа регистрирует объект в модели формы, но откладывает создание его графических дескрипторов.
  3. Если пользователь закрывает документ, так и не открыв вкладку с форматированным документом, платформа запускает процедуру деинициализации элементов формы. Деструктор пытается освободить неопределенные или некорректно инициализированные ресурсы компонента fmtd.dll, что провоцирует ошибку нарушения доступа к памяти (Access Violation) и аварийный вылет 1CV8C.exe.
  4. Если же пользователь вручную переходит на вкладку с форматированным документом, графический контекст создается корректно, и при закрытии формы деструкторы отрабатывают штатно без аварий.

Способ 1. Принудительная инициализация страницы при открытии формы

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

Посмотрим на пример реализации в клиентском обработчике ПриОткрытии:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Сохраняем исходную активную страницу
    ИсходнаяСтраница = Элементы.ГруппаСтраницы.ТекущаяСтраница;
    
    // Кратковременно активируем страницу с динамическим форматированным документом
    Элементы.ГруппаСтраницы.ТекущаяСтраница = Элементы.СтраницаБазаЗнаний;
    
    // Возвращаем пользователя на исходную страницу
    Элементы.ГруппаСтраницы.ТекущаяСтраница = ИсходнаяСтраница;
КонецПроцедуры

Такое переключение заставляет платформу выполнить отрисовку элемента ФорматированныйДокумент при старте формы, благодаря чему при закрытии окна деструктор отработает без сбоев.

Способ 2. Программное удаление элемента перед закрытием формы

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

Реализуем удаление элемента в процедуре-обработчике ПередЗакрытием:


&НаКлиенте
Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)
    // Проверяем наличие элемента и удаляем его перед уничтожением окна
    ЭлементФорматированныйДокумент = Элементы.Найти("ПолеФорматированногоДокумента");
    Если ЭлементФорматированныйДокумент <> Неопределено Тогда
        Элементы.Удалить(ЭлементФорматированныйДокумент);
    КонецЕсли;
КонецПроцедуры

Способ 3. Статическое размещение элемента в конфигураторе

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

Выполним следующие действия:

  1. Откроем форму объекта в конфигураторе.
  2. Добавим реквизит формы с типом ФорматированныйДокумент в дерево реквизитов вручную.
  3. Разместим элемент управления на нужной странице группы страниц.
  4. Если отображение вкладки или поля зависит от прав, настроек или условий данных, будем управлять его видимостью через свойство Видимость = Истина / Ложь вместо полного программного удаления и создания структуры формы в рантайме.

Способ 4. Использование поля HTML-документа или многострочного текста

Если специфика задачи позволяет изменить тип отображаемых данных, проанализируем альтернативные варианты элементов управления:

  1. Поле HTML документа: Если требуется сохранять оформление текста (стили, цвета, списки), можно использовать строковый реквизит неограниченной длины и связать его с элементом формы вида Поле HTML документа. Механизм HTML использует другие библиотеки отображения и не подвержен сбою при отложенной инициализации.
  2. Многострочное текстовое поле: Если форматирование текста (жирность, курсив, заголовки) не является обязательным, заменим тип реквизита на обычную строку, а для элемента формы включим флаг МногострочныйРежим = Истина.

Способ 5. Обновление версии платформы 1С

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

← На главную