Вопрос, который стоит перед разработчиками, использующими Delphi 6, заключается в обнаружении ошибки, связанной с копированием параметров при работе с событиями OLE. Проблема заключается в том, что порядок параметров при вызове событий меняется дважды: сначала в импортированной заголовочной части, а затем в методе TServerEventDispatch.Invoke. Это приводит к тому, что при передаче параметров типа Var_Array возникает утечка памяти.
Описание проблемы
При импорте тиблицы типов (TLB) в Delphi 6, наблюдается ошибка, когда порядок параметров при вызове событий меняется. Это происходит как минимум в двух местах: в импортированной заголовочной части и в методе TServerEventDispatch.Invoke. Эта проблема обсуждается на форуме поддержки разработчиков, ссылка на который доступна здесь.
В коде, который работает с событиями, используется копирование аргументов в массив VarArray для передачи обработчику событий, после чего происходит копирование VarArray обратно в аргументы после вызова. В примере кода, представленном ниже, видно, что данные копируются в VarArray, затем вызывается прокси-класс сервера, и после этого данные копируются обратно:
// Установка размера массива
SetLength(VarArray, ParamCount);
// Копирование данных
for I := Low(VarArray) to High(VarArray) do
VarArray[I] := OleVariant(TDispParams(Params).rgvarg^[I]);
// Вызов прокси-класса сервера
if FServer <> nil then FServer.InvokeEvent(DispID, VarArray);
// Копирование данных обратно
for I := Low(VarArray) to High(VarArray) do
OleVariant(TDispParams(Params).rgvarg^[I]) := VarArray[I];
// Освобождение памяти массива
SetLength(VarArray, 0);
Однако при работе с параметром типа Var_Array возникает утечка памяти, и одно из возможных решений заключается в пропуске копирования данных обратно в случае с Var_Array. Но для сохранения функциональности необходимо более сложное решение, которое может потребовать рекурсивного копирования данных.
Анализ проблемы
Пользователи сталкиваются с трудностями в отладке, так как не могут проследить вызов ниже уровня TServerEventDIspatch.Invoke. Предполагается, что копирование данных обратно в параметры может привести к добавлению ссылки на массив, что не позволяет ему быть освобожденным как обычно.
Подтвержденный ответ
После дополнительного анализа и изучения документации по Delphi, было выяснено, что при копировании значения, содержащего массив, в переменную типа Variant, происходит создание копии. Это подтверждается информацией из официальной документации Delphi. Освобождение памяти, связанной с предыдущим значением Variant, происходит при назначении нового значения переменной.
Таким образом, проблема заключается в том, что при копировании массива обратно в параметры, происходит создание новой копии данных, которую COM-объект не ожидает и не освобождает. Это приводит к утечке памяти.
Решением проблемы может быть изменение кода таким образом, чтобы копирование значений в параметры происходило только если параметр отмечен как передаваемый по ссылке. Это можно определить по значению поля vt структуры TVariantArg. Если параметр передается по ссылке, необходимо соответствующим образом обновить значение в параметрах.
Пример кода
Вот пример кода, который решает проблему утечки памяти, учитывая, что параметр передается по ссылке:
if ((TDispParams(Params).rgvarg^[I].vt and VT_BYREF) <> 0) then begin
OleVariant(TDispParams(Params).rgvarg^[I]) := VarArray[I];
end;
Этот код проверяет, передается ли параметр по ссылке, и если да, то осуществляется копирование значения из VarArray в параметры.
Заключение
Утечка памяти в Delphi 6 при работе с параметрами типа Var_Array в компоненте OleServer.pas может быть решена путем изменения логики копирования параметров. Важно понимать, как работает передача параметров по значению и по ссылке, а также как Delphi управляет памятью при работе с объектами OLE. С учетом этих знаний можно избежать утечек памяти и обеспечить корректную работу приложений, написанных на Delphi.
У разработчиков Delphi 6 обнаружена проблема с утечкой памяти при работе с копированием параметров типа `Var_Array` в компоненте `OleServer.pas`, связанная с изменением порядка параметров при вызове событий OLE.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS