Проблема с удалением указателя на TMultipartFormData в Delphi 12.3 и её решение
Введение
В последнее время многие разработчики, использующие C++ Builder и Delphi, столкнулись с проблемой при работе с классом TMultipartFormData из модуля System.Net.Mime.pas. В частности, при переходе с версии 11.3 на 12.3 возникает краш при попытке удаления указателя на объект этого класса. В этой статье мы подробно разберём причины этой проблемы и предложим несколько вариантов её решения.
Описание проблемы
Как сообщил пользователь alank2 на форуме Embarcadero, при построении проекта в C++ Builder 11.3 с использованием TMultipartFormData всё работает корректно, но при переходе на версию 12.3 возникает краш при попытке удаления указателя на объект этого класса.
Основные симптомы:
- Краш происходит при вызове FStream.Free
- Проблема связана с методом AddStream
- В версии 12.3 были внесены изменения в реализацию System.Net.Mime.pas
Анализ изменений между версиями
При сравнении кода между версиями 11.3 и 12.3 обнаруживаются значительные изменения в реализации TMultipartFormData. Ключевое изменение касается метода AddStream:
Основная причина проблемы заключается в том, что в C++ Builder при вызове:
mfd->AddStream("name", send, "value");
происходит неявное преобразование строкового литерала "value" в булево значение true (из-за особенностей разрешения перегрузок в C++), что приводит к вызову новой версии метода с параметром AOwnsStream=true. В результате, при уничтожении объекта TMultipartFormData происходит попытка освобождения потока, который уже был освобождён в коде приложения.
Решение проблемы
1. Использование правильной перегрузки метода
Самый простой способ избежать проблемы - явно указать, что поток не должен освобождаться автоматически:
mfd->AddStream("name", send, false, "value", "");
2. Явное приведение типов
Чтобы гарантированно вызвать deprecated-версию метода и получить предупреждение компилятора, можно использовать явное приведение типов:
Рекомендуется переписать код для использования новой версии метода с явным указанием параметра AOwnsStream:
// Пример на Object Pascal
var
mfd: TMultipartFormData;
send: TMemoryStream;
begin
send := TMemoryStream.Create;
try
mfd := TMultipartFormData.Create(True);
try
mfd.AddStream('name', send, False, 'value');
// ... использование mfd ...
finally
mfd.Free;
end;
finally
send.Free;
end;
end;
4. Обработка deprecated-предупреждений
В Delphi deprecated-версии методов вызывают предупреждения компилятора. В C++ Builder эта функциональность работает не всегда корректно, особенно в классическом компиляторе bcc32. Для получения предупреждений можно:
Включить все предупреждения компилятора (кроме, возможно, 8057)
Использовать современный компилятор Clang вместо классического bcc32
Вручную проверять использование deprecated-методов при рефакторинге
Альтернативное решение
Если по каким-то причинам невозможно изменить код вызова AddStream, можно создать класс-обёртку, который будет корректно работать в обеих версиях:
Проблема с удалением указателя на TMultipartFormData в Delphi 12.3 возникает из-за изменений в API класса и особенностей разрешения перегрузок в C++ Builder. Наиболее правильным решением является использование новой версии метода AddStream с явным указанием параметра AOwnsStream. Это не только решает проблему с крашем, но и делает код более явным и понятным.
Разработчикам, работающим с C++ Builder, следует быть особенно внимательными при вызове методов Delphi из C++ кода, так как неявные преобразования типов могут привести к неожиданному поведению. Рекомендуется всегда проверять, какая именно перегрузка метода вызывается, и при необходимости использовать явные приведения типов.
Дополнительные рекомендации
Всегда проверяйте журнал изменений (Release Notes) при обновлении версии Delphi/C++ Builder
Включайте максимальный уровень предупреждений компилятора
Регулярно проверяйте код на использование deprecated-функций
При работе с чужими компонентами учитывайте, кто владеет объектами (ownership)
Используйте инструменты статического анализа кода для выявления потенциальных проблем
Следуя этим рекомендациям, вы сможете избежать подобных проблем при обновлении версий среды разработки и создавать более надёжный и стабильный код.
В статье рассматривается проблема с удалением указателя на TMultipartFormData в Delphi 12.3, вызванная изменением API, и предлагаются несколько решений, включая использование правильной перегрузки метода, обновление кода и создание обертки.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.