2016-08-30 1 views
1

В Delphi есть две службы. Одна служба запускается на сервере, а другая служба выполняется на клиентах. Эти две службы обмениваются данными между клиентом и сервером. В этом случае серверная служба просит клиентов отправлять данные, однако через день или около того выделенная память на сервере превышает ее физический размер. После некоторых исследований я обнаружил, что что-то не так в этих двух функциях ниже.Имеет ли этот код Delphi утечку памяти?

У меня есть утечка памяти в следующем коде? Сервис

Сервер:

function TServerMethods.LogInMngr_GetAllUsers(): TList<TLogInClass>; 
Var 
    C: TDBXCommand; 
Begin 
    C := CreateCommand('LogInMngr_GetAllUsers'); 
    try 
    C.ExecuteUpdate; 
    Result := GetValue<TList<TLogInClass>>(C.Parameters[RP]); 
    finally 
    C.Free; 
    end; 
end; 

Client Service:

function TLogInMngrClass.GetAllUsers(status: TLogInStatus = lisUnknown): TList<TLogInClass>; 
var 
    LogIn: TLogInItem; 
    LogInTemp: TLogInClass; 
    UsedProg: TUsedItem; 
begin 
    Result := TList<TLogInClass>.Create; 

    for LogIn in LogInList do 
    if (status = lisUnknown) or (LogIn.Status = Integer(status)) then 
     for UsedProg in LogIn.UsedProgList do 
     begin 
     LogInTemp:=TLogInClass.Create(LogIn.ClientID, LogIn.ComputerName, LogIn.UserName, '', ''); 
     LogInTemp.LogInTime := DateTimeToFileTime(UsedProg.AccessTime); 
     LogInTemp.Status := LogIn.Status; 
     LogInTemp.ProgName := UsedProg.ItemName; 
     LogInTemp.ProgVersion := UsedProg.ItemInfo; 

     Result.Add(LogInTemp); 
     end; 
end; 

данных в классе TLogInClass и результат возвращается в общий список класса TLogInClass с помощью TDSServer.

+1

«* Имеет ли этот код delphi утечку памяти?» «Наверное, да, но в коде, который вы опубликовали, нет никаких доказательств. Нет никаких доказательств того, как освобождается «TList ». Также это должен быть 'TObjectList', который владеет значениями, но это всего лишь предположение, что ответы будут – fantaghirocco

+1

Вы не показываете, как оба результата' TList 'освобождены. Пожалуйста, добавьте эту информацию. –

+0

Либо создайте [mcve], либо выполните некоторую отладку. –

ответ

0

Как уже упоминалось, вы не показывают, как «результат» функции на стороне клиента является Memory- удалось.

Я подозреваю, что клиент GetAllUsers вызывается несколько раз, что, в свою очередь, вызывает многократное срабатывание Create и увеличивает потребление памяти.

Помимо этого, мне всегда сложно управлять возвратами объектов по функциям. Трудно определить, как и когда «результат» должен быть освобожден и освобождены ли они.

В настоящее время функция на стороне сервера не является «осведомленной», ответственной за управление результатом.

Я хотел бы переписать эту функцию в процедуру с параметром, как это:

procedure TServerMethods.LogInMngr_GetAllUsers (var userList: TObjectList<TLogInClass>); 
begin 
    if not assigned(userList) then 
    raise Exception.Create('userList not instantiated'); 
    ... 
end; 

, а затем вызвать процедуру этого:

var  
    tmpUsers: TObjectList<TLogInClass>; 
begin 
tmpUsers:=TObjectList<TLogInClass>.Create; 
try 
    ServerMethods.LogInMngr_GetAllUsers(tmpUsers); <--- or whatever you call the ServerMethods class 
    ..... 
finaly 
    tmpUsers.Free; 
end; 

конец;

Таким образом, вы можете четко управлять жизненным циклом списков.

Возможно, я не следую вашему дизайну или пропущу некоторые биты, но я думаю, что вы получаете возможность использовать процедуры вместо функций для управления объектами.

+0

Функции, возвращающие новые значения, являются точными, пока они включают Create в имени, чтобы указать, что они создают новые экземпляры. Относитесь к ним, когда вы обращаетесь к конструкторам.Ваши так называемые улучшения утечек в случае исключения. Вы должны попробовать наконец. –

+0

@DavidHeffernan: Я не сказал, что они не в порядке. Я сказал, что менеджер ИМО легче управлять. Спасибо за это. Теперь я редактировал код, и он «двойной», так называемый улучшенный –

0

Вы можете легко найти с этим ...

Memory Leak Notification in Delphi

ReportMemoryLeaksOnShutdown := DebugHook <> 0;   
+0

Это не обнаружит утечек. Не будет обнаружен утечек, когда память должна быть выпущена во время выполнения, которая выдается только при завершении работы. Важно для длительных процессов. –