Почему падает rphost при использовании метода Сдвинуть() в ФорматированномДокументе и как это исправить?

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

В процессе разработки и поддержки конфигураций на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с неожиданным поведением системы. Одной из наиболее критичных проблем является аварийное завершение рабочего процесса rphost.exe (или 1cv8.exe в файловом варианте), которое приводит к немедленному прерыванию сеансов всех пользователей. Рассмотрим детально одну из таких ситуаций, связанную с объектом ФорматированныйДокумент и методом Сдвинуть(), которая проявляется на версиях платформы 8.3.14.х и 8.3.15.х.

Суть проблемы и анализ ситуации

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


ФД = Новый ФорматированныйДокумент;
П1 = ФД.Элементы.Добавить(); // Добавляем первый элемент
П2 = ФД.Элементы.Добавить(); // Добавляем второй элемент
ФД.Элементы.Сдвинуть(0, 1);   // Пытаемся сдвинуть первый элемент на одну позицию вперед

В этот момент платформа генерирует Access Violation (ошибка доступа к памяти). Разберем, что происходит "под капотом": метод Сдвинуть() на уровне ядра платформы некорректно обрабатывает индексы коллекции при работе с объектами сложной структуры, коим является ФорматированныйДокумент. Вместо перестановки указателей в памяти, происходит обращение к неинициализированному участку, что и вызывает моментальный краш процесса.

Симптомы в различных режимах работы

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

  1. Клиент-серверный вариант: Падает процесс rphost.exe. Поскольку один рабочий процесс может обслуживать десятки пользователей, все они получают сообщение "Сеанс отсутствует или завершен" и теряют несохраненные данные. После падения кластер 1С пытается перезапустить процесс, что создает циклическую нагрузку.
  2. Файловый вариант: Программа просто закрывается с предложением отправить дамп в Microsoft или 1С. Работа одного пользователя прерывается мгновенно.

Проанализируем пример для трех элементов, который также вызывает ошибку:


ФД = Новый ФорматированныйДокумент; 
П1 = ФД.Элементы.Добавить(); 
П2 = ФД.Элементы.Добавить(); 
П3 = ФД.Элементы.Добавить(); 
ФД.Элементы.Сдвинуть(1, 1); // Перемещение второго элемента в конец коллекции

Как мы видим, критическая ошибка возникает именно при попытке сдвинуть элемент в сторону конца коллекции или на граничные индексы.

Официальное решение: Обновление платформы

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

Рекомендация: Если ваша конфигурация (например, Управление торговлей 11 или кастомные CRM-системы) активно использует ФорматированныйДокумент для работы с электронными письмами, обновление платформы является приоритетной задачей для обеспечения стабильности сервера.

Программный обход (Workaround) без обновления платформы

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

Рассмотрим альтернативный алгоритм замены метода Сдвинуть(Элемент, Дистанция). Вместо прямого сдвига мы выполним пересоздание элемента на нужной позиции. Разберем по шагам:

  1. Определяем текущий индекс элемента, который нужно переместить.
  2. Рассчитываем новый целевой индекс.
  3. Копируем содержимое элемента (если это текст или картинка).
  4. Удаляем старый элемент.
  5. Вставляем новый элемент по целевому индексу.

Пример безопасного кода для перемещения элемента:


// Вместо ФД.Элементы.Сдвинуть(СтарыйИндекс, 1);
ЭлементДляПереноса = ФД.Элементы.Получить(СтарыйИндекс);
НовыйИндекс = СтарыйИндекс + 1;

// Если нам нужно сохранить содержимое (например, текст параграфа)
ТекстЭлемента = "";
Если ТипЗнч(ЭлементДляПереноса) = Тип("ТекстФорматированногоДокумента") Тогда
    ТекстЭлемента = ЭлементДляПереноса.Текст;
КонецЕсли;

ФД.Элементы.Удалить(СтарыйИндекс);
НовыйЭлемент = ФД.Элементы.Вставить(НовыйИндекс);

Если ТипЗнч(НовыйЭлемент) = Тип("ТекстФорматированногоДокумента") Тогда
    НовыйЭлемент.Текст = ТекстЭлемента;
КонецЕсли;

Этот метод, хоть и выглядит как "костыль", гарантирует, что rphost не упадет, так как мы используем базовые операции манипуляции коллекцией, которые реализованы в платформе корректно.

Почему это критично для CRM и почтовых модулей?

Проанализируем ситуацию: многие современные решения (например, CRM от сторонних разработчиков или встроенные почтовые клиенты в 1С) используют ФорматированныйДокумент как основной редактор текста писем. При визуальном редактировании (например, нажатии кнопок "вверх/вниз" для изменения порядка вложений или блоков текста) вызывается именно метод Сдвинуть().

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

Выводы

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

  1. Обновиться до актуального защищенного релиза платформы (минимум 8.3.15.1747 или 8.3.17.1386).
  2. Если обновление невозможно — провести аудит кода и заменить все вызовы Сдвинуть() в коллекциях ФорматированногоДокумента на связку Удалить() + Вставить().
  3. При возникновении подобных дампов всегда проверять Bug Board по номеру ошибки 10214878, чтобы убедиться в отсутствии регрессий в более новых версиях.

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

← На главную