Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Освободить из основной программы класс объявленный в коде FastScript  [new]
vdix
Member

Откуда:
Сообщений: 29
Имплементировал в серверном приложение FastScript, одна из функций должна возвращать структуру, но в виду того, что record не поддерживается фастскриптом, приходится создавать класс. Будь это клиентское приложение, особой проблемы не возникло бы, но на сервере обнаружилась неприятная ситуация: утечка памяти. Класс, созданный в коде FastScript, не освобождается, потому что является результатом функции фастскрипта, а передаётся он в код основной программы сервера.

Код в фастскрипте выглядит примерно так:
function OnCheckRequest(ParamIn: variant): TMyRequestResponse;
begin
  Result := TMyRequestResponse.Create;
  Result.ParamOut1 := 'something';
  Result.ParamOut2 := True;
end;

Что я попытался реализовать в коде самого серверного приложения:
/// вызываю функцию фастскрипта и получаю результат в Х виде класса TMyRequestResponse
X := TMyRequestResponse(IntegerAScript.CallFunction1(fsScript, 'OnCheckRequest', ParamsVA)));
try
/// обработка результата всякое
/// ...

/// попытался найти и освободить инициализированную переменную класса TMyRequestResponse, но безуспешно:
{
    for I := 0 to Pred(fsScript.Count) do
    begin
      V := fsScript.Items[I];
      if V is TfsClassVariable then
        if TfsClassVariable(V).ClassRef.ClassName = 'TMyRequestResponse' then
        begin
          //if Integer(TfsClassVariable(V).ClassRef) = Integer(X) then // это никогда не происходит, видимо, в код Делфы передаётся копия класса, а не референс
          begin
            TfsClassVariable(V).Free;
            fsScript.Remove(V); // это сделать можно, но чуть попозже получим ошибку List index out of bounds. если не освобождать переменную строчкой выше - результат тот же
          end;
        end;
    end;
}
/// освобождаю локальную переменную, но утечку памяти это не исправляет
finally
  FreeAndNil(X);
end;

Если кто может предложить правильный вариант или альтернативное решение - буду весьма благодарен.
З.Ы. Возвращать результат через глобальную переменную/объект фастскрипта - не вариант, сервер работает в асинхронном режиме.

Сообщение было отредактировано: 31 мар 21, 14:48
31 мар 21, 14:51    [22302525]     Ответить | Цитировать Сообщить модератору
 Re: Освободить из основной программы класс объявленный в коде FastScript  [new]
DimaBr
Member

Откуда:
Сообщений: 12043
Тестовый пример, который проходит (у меня) без утечек
+
type
TMyObject = class(TComponent)
  private
    fParam: variant;
    procedure DoEvent;
  published
    property Param: Variant read fParam write fParam;
end;

TFunctions = class(TfsRTTIModule)
  constructor Create(AScript: TfsScript); override;
end;

{ TFunctions }

constructor TFunctions.Create(AScript: TfsScript);
begin
  inherited;
  AScript.AddClass(TMyObject,'TComponent')
end;

procedure TForm1.Button1Click(Sender: TObject);
var X: TMyObject;
    ParamsVA: Variant;
begin
  ParamsVA := VarArrayCreate([0,0],varVariant);
  ParamsVA[0] := 'Test';
  fsScript1.Lines.Clear;
  fsScript1.Lines.Add('function OnCheckRequest(ParamIn: variant): TMyObject;');
  fsScript1.Lines.Add('begin');
  fsScript1.Lines.Add('  Result := TMyObject.Create(nil);');
  fsScript1.Lines.Add('  Result.Param := ParamIn;');
  fsScript1.Lines.Add('end;');
  fsScript1.Lines.Add('begin');
  fsScript1.Lines.Add('end.');
  fsScript1.AddRTTI;
  fsScript1.Compile;
  X := TMyObject(integer(fsScript1.CallFunction1('OnCheckRequest', ParamsVA)));
  try
    X.DoEvent();
  finally
    X.Free;
  end;
end;

{ TMyObject }

procedure TMyObject.DoEvent;
begin
  ShowMessage(Param);
end;

initialization
  fsRTTIModules.Add(TFunctions);

finalization
  fsRTTIModules.Remove(TFunctions);

end.
31 мар 21, 15:58    [22302585]     Ответить | Цитировать Сообщить модератору
 Re: Освободить из основной программы класс объявленный в коде FastScript  [new]
DimaBr
Member

Откуда:
Сообщений: 12043
и появляется утечка, если добавить (и не уничтожить) ещё один объект.
Картинка с другого сайта.
31 мар 21, 16:01    [22302590]     Ответить | Цитировать Сообщить модератору
 Re: Освободить из основной программы класс объявленный в коде FastScript  [new]
L_argo
Member

Откуда:
Сообщений: 1456
Создайте процедуру для освобождения ресурса. Зарегистрируйте ее в ФР. Вызывайте ее в конце скрипта.
31 мар 21, 16:33    [22302610]     Ответить | Цитировать Сообщить модератору
 Re: Освободить из основной программы класс объявленный в коде FastScript  [new]
Fr0sT-Brutal
Member

Откуда:
Сообщений: 682
За приведение к указателю через каст к integer еще не били кактусом по рукам?
31 мар 21, 17:15    [22302634]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить