PDA

Ver la Versión Completa : Consulta sobre Web services y Delphi


Gercondi
05-07-2012, 22:36:57
Saludos a todos los que hacen parte de este foro.

Tengo una aplicación que contiene un modulo cliente y uno servidor. El modulo de servidor lee cada 5 segundos información de varios web services y la almacena en unos Tclientdataset, para que el modulo cliente pueda utilizar estos datos.

Mi duda es: Es normal que aún cuando estoy liberando (con Free()) todos los objetos que se crean (con Create()) para el llamado a los webservices la memoria virtual del proceso crezca aproximada mente un mega cada 2 horas?

Uno de los procesos que mas hace crecer la memoria virtual es el siguiente:

procedure LlamadosWS.getOperadores;
var
L_SPRCMXCRAFT: SPRCMXCRAFTQuery;
xORGID, xCRAFT : SPRCMXCRAFT1.Array_Of_MXStringQueryType;
ListaOperadores : SPRCMXCRAFTSet;
I : integer;
op_HTTPRIO : THTTPRIO;
begin
try
L_SPRCMXCRAFT := SPRCMXCRAFTQuery.Create;

SetLength(xORGID,1);
xORGID[0] := SPRCMXCRAFT1.MXStringQueryType.Create;
xORGID[0].&operator := SPRCMXCRAFT1.QueryOperatorType.igual;
xORGID[0].Text := _OrgID;

L_SPRCMXCRAFT.LABORCRAFTRATE := SPRCMXCRAFT1.LABORCRAFTRATE3.Create;
L_SPRCMXCRAFT.LABORCRAFTRATE.ORGID := xORGID;


SetLength(xCRAFT,1);
xCRAFT[0] := SPRCMXCRAFT1.MXStringQueryType.Create;
xCRAFT[0].Text := _ESPECIALIDADES;

L_SPRCMXCRAFT.LABORCRAFTRATE.CRAFT := xCRAFT;


op_HTTPRIO := THTTPRIO.Create(nil);
op_HTTPRIO.HTTPWebNode.UserName := Datamodule1.UsuarioCFZ;
op_HTTPRIO.HTTPWebNode.Password := Datamodule1.PasswordCFZ;


ListaOperadores := GetSPRCMXCRAFTPortType(False,'',op_HTTPRIO).QuerySPRCMXCRAFT(L_SPRCMXCRAFT);

L_SPRCMXCRAFT.Free;
xORGID[0].Free;
xCRAFT[0].Free;

with DataModule2 do
begin

CDS_Operadores_WS.EmptyDataSet;
CDS_Operadores_WS.Close;
CDS_Operadores_WS.Open;

Datamodule2.LimpiarCDS(CDS_Operadores_WS);

for I := 0 to Length(ListaOperadores) - 1 do
begin

try
if ListaOperadores[i].LABOR[0].STATUS.text = 'ACTIVO' then
begin
try
CDS_Operadores_WS.InsertRecord([ListaOperadores[i].LABORCODE.text,
ListaOperadores[i].LABOR[0].PERSON[0].FIRSTNAME.Text + ' ' + ListaOperadores[i].LABOR[0].PERSON[0].LASTNAME.Text,
ListaOperadores[i].CRAFT.text ,
ListaOperadores[i].LABOR[0].PERSON[0].STATUS.Text,
ListaOperadores[i].LABOR[0].PERSONID.Text]);
finally
ListaOperadores[i].Free;
end;

end;
except
Continue;
end;

end;
end;
finally
ListaOperadores := nil;
end;
end;

Ñuño Martínez
06-07-2012, 21:01:18
Es muy difícil responder. Sin embargo, he visto que al final asignas un nil a una variable. Recuerda que con eso no liberas memoria.

Me han recomendado muchas veces la herramienta Valgrind (http://valgrind.org/), aunque nunca la he usado por vagancia. Quizá te sirva para encontrar dónde reserva memoria que luego no libera.

clauxs88
20-07-2016, 16:27:00
Al igual que el colega @Gercondi, tengo un Ws que corre entre los servicios de Windows y al realizar las tareas de consumir parametros y devolver resultados el Proceso crece y sigue creciendo a menos que cada tanto reinicie mi Servicio con un net restart WSDemonConuslta; esto pasa inclusive cuando libero los objetos que cree en el proceso con variable:=nil; variable.Free, pero sin importancia.

Algún aporte?

Ñuño Martínez
21-07-2016, 11:21:26
Como dije hace cuatro años, es difícil responder. Y también, asignar "nil" no libera memoria. El siguiente código no libera memoria:

Objecto := nil;
Objeto.Free;

Es más, te dará un error puesto que estás intentando llamar a un método de un objeto que no existe (el objeto nil no existe). El código debería ser este:

Objeto.Free;
Objeto := nil;


O lo que es lo mismo:

FreeAndNil (Objeto);

AgustinOrtu
21-07-2016, 18:32:12
Si invocas a free sobre un objeto que es nil no se eleva una excepción

Ñuño Martínez
21-07-2016, 21:37:06
Si invocas a free sobre un objeto que es nil no se eleva una excepción
¿Seguro? Me parece recordar que sí provoca un error de ejecución por memoria re-liberada o algo así. Aunque puede que esto sea algo exclusivo de Free Pascal. :confused:

AgustinOrtu
22-07-2016, 05:13:22
Totalmente seguro

El metodo free esta implementado asi (o muy similar, sacando los IFDEF segun la plataforma)


procedure TObject.Free;
begin
if Self <> nil then
Destroy;
end;


Esto es totalmente seguro, jamas te va a dar error:


var
Obj: TObject;
begin
Obj := nil;
while True do
Obj.Free;
end;


Ahora, el problema es que el destructor no deja la instancia "limpia" (no asigna nil cuando termina, no deja la memoria en 0000)

Esto si te eleva una excepcion AcessViolation:


var
Obj: TObject;
begin
Obj := TObject.Create;
Obj.Free; // todo bien
Obj.Free; // AccessViolation
end;

Ñuño Martínez
22-07-2016, 11:21:45
Ok. Ahora sí me quedó claro. Será entonces eso, que no "limpio" la variable de referencia. Gracias. :)