Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Решение проблемы с удалением указателя на TMultipartFormData в Delphi 12.3

Delphi , Компоненты и Классы , Коллекции

Проблема с удалением указателя на 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:

// Старая версия (11.3)
procedure AddStream(const AField: string; AStream: TStream;
  const AFileName: string = ''; const AContentType: string = '';
  AHeaders: TStrings = nil); overload;

// Новая версия (12.3)
procedure AddStream(const AField: string; AStream: TStream;
  const AFileName: string = ''; const AContentType: string = '';
  AHeaders: TStrings = nil); overload; deprecated 'Use AddStream with AOwnsStream parameter';

procedure AddStream(const AField: string; AStream: TStream; 
  AOwnsStream: Boolean; const AFileName: string = ''; 
  const AContentType: string = ''; AHeaders: TStrings = nil); overload;

Причина краша

Основная причина проблемы заключается в том, что в C++ Builder при вызове:

mfd->AddStream("name", send, "value");

происходит неявное преобразование строкового литерала "value" в булево значение true (из-за особенностей разрешения перегрузок в C++), что приводит к вызову новой версии метода с параметром AOwnsStream=true. В результате, при уничтожении объекта TMultipartFormData происходит попытка освобождения потока, который уже был освобождён в коде приложения.

Решение проблемы

1. Использование правильной перегрузки метода

Самый простой способ избежать проблемы - явно указать, что поток не должен освобождаться автоматически:

mfd->AddStream("name", send, false, "value", "");

2. Явное приведение типов

Чтобы гарантированно вызвать deprecated-версию метода и получить предупреждение компилятора, можно использовать явное приведение типов:

mfd->AddStream(_D("name"), send, String(_D("value")));

3. Обновление кода для работы с новой версией

Рекомендуется переписать код для использования новой версии метода с явным указанием параметра 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. Для получения предупреждений можно:

  1. Включить все предупреждения компилятора (кроме, возможно, 8057)
  2. Использовать современный компилятор Clang вместо классического bcc32
  3. Вручную проверять использование deprecated-методов при рефакторинге

Альтернативное решение

Если по каким-то причинам невозможно изменить код вызова AddStream, можно создать класс-обёртку, который будет корректно работать в обеих версиях:

type
  TMultipartFormDataHelper = class helper for TMultipartFormData
  public
    procedure SafeAddStream(const AField: string; AStream: TStream; 
      const AFileName: string = ''; const AContentType: string = '';
      AHeaders: TStrings = nil);
  end;

procedure TMultipartFormDataHelper.SafeAddStream(const AField: string; 
  AStream: TStream; const AFileName, AContentType: string; AHeaders: TStrings);
begin
  {$IFDEF VER350} // Delphi 11.3
    AddStream(AField, AStream, AFileName, AContentType, AHeaders);
  {$ELSE}
    AddStream(AField, AStream, False, AFileName, AContentType, AHeaders);
  {$ENDIF}
end;

Заключение

Проблема с удалением указателя на TMultipartFormData в Delphi 12.3 возникает из-за изменений в API класса и особенностей разрешения перегрузок в C++ Builder. Наиболее правильным решением является использование новой версии метода AddStream с явным указанием параметра AOwnsStream. Это не только решает проблему с крашем, но и делает код более явным и понятным.

Разработчикам, работающим с C++ Builder, следует быть особенно внимательными при вызове методов Delphi из C++ кода, так как неявные преобразования типов могут привести к неожиданному поведению. Рекомендуется всегда проверять, какая именно перегрузка метода вызывается, и при необходимости использовать явные приведения типов.

Дополнительные рекомендации

  1. Всегда проверяйте журнал изменений (Release Notes) при обновлении версии Delphi/C++ Builder
  2. Включайте максимальный уровень предупреждений компилятора
  3. Регулярно проверяйте код на использование deprecated-функций
  4. При работе с чужими компонентами учитывайте, кто владеет объектами (ownership)
  5. Используйте инструменты статического анализа кода для выявления потенциальных проблем

Следуя этим рекомендациям, вы сможете избежать подобных проблем при обновлении версий среды разработки и создавать более надёжный и стабильный код.

Создано по материалам из источника по ссылке.

В статье рассматривается проблема с удалением указателя на TMultipartFormData в Delphi 12.3, вызванная изменением API, и предлагаются несколько решений, включая использование правильной перегрузки метода, обновление кода и создание обертки.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




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


:: Главная :: Коллекции ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-06-04 06:14:08/0.0059888362884521/0