PDA

Ver la Versión Completa : error.. out of memory...


CarlosHernandez
06-03-2007, 19:38:37
hola a todos los foristas again..

hago una consulta muy larga con union, left join, etc, etc, de varias tablas, unida con un while do, ademas de eso hay otro while do repitiendo el proceso otra vez, y hay impresiones de reportes, llena como unas 15 variables, en fin..


variables;
consulta1.sql.add();
llenar variables.

while not consulta1.eof do begin
//if
consulta2.sql.add('aqui va una consulta muy larga');
//if
while not consulta1.eof do begin

// una serie de if validando todo
end;

qreport.print;
//el reporte tiene cada banda con codigo validando muchas mas cosas
end;


bueno se que no es la manera, pero trato de poner mas bien es la estructura porque el codigo ni ya me acuerdo que hace, jeje, y cuando voy en el while do por el registro 20 sale en delphi out of memory y se cuelga la maquina...

ha manera de liberar memoria, o liberar algo para que no consuma tanto, porque abro el administrador de tarea y veo que la aplicacion va 100.000 kb, y eso no es factible... gracias

y si ncesitan algo mas me avisan por favor

y ademas ¿cual es la causa de ese error?

tambien me da otro error

access violation at address 000a0d20. read of address 000a0d20

uso delphi 6 y firebird 1.5

ContraVeneno
06-03-2007, 19:51:25
Pues supongo que habría que redefinir la consulta.
Tratar de evitar a toda costa el clásico "Select *".
Que cada línea de tu consulta este en su propia línea "consulta2.sql.add("

Fuera de eso y sin más detalles, me he quedado sin ideas

Lepe
06-03-2007, 19:59:55
El "out of memory" queda claro de qué es ¿no?. Yo creo que estas metiendo la gamba por ahí en la creación de algunos componentes.

No lo achacaría a la cantidad innerjoins... puesto que eso es trabajo de Firebird, lo que sí miraría es la cantidad de registros que devuelve.... aunque para ser un informe no creo que devuelva 300.000 registros (por decir un número alto).

Total, que debe mirarse el código exacto para decir algo.

El access violation es por acceder a un objeto que ya no está en memoria porque se ha llamado a .Free

Saludos

CarlosHernandez
06-03-2007, 20:52:35
la cuestion es la siguiente, yo con este codigo realizo la union de varios campos, de una tabla de personal, y otra de horas, validaqndo todo, y haciendo una validacion solo para que me tome 1 entrada y ultima salida por dia, todo el mes para imprimirlo en un reporte, y el union lo uso para pasar el registro que no este en la tabla hora ejmeplo, un sabado que no tenga asistencia, lo pone como registro vacio, para vizualizarlo en el reporte, y se vean los 31 dias del mes. ah tambien tengo fotos dentro de la bases de datos


var
op,b,boton:integer;
nombref:PChar;
begin


if RadioButton1.Checked=true then op:=1; //diario


case op of


1:begin


b:=0;
with tabla.IBQuerypersonal do begin //*-966222

SQL.Clear;
Close; // // and status='+QuotedStr('Activo')+' // //
sql.Add('select * from personal where ( Ubicacion='+QuotedStr('CIRCUITO DE TRABAJO')+' or
Ubicacion='+QuotedStr('DEPARTAMENTO1')+' ) and status='+QuotedStr('Activo')+'
and ( modcargo='+QuotedStr('Fijo')+' or modcargo='+QuotedStr('Contratado')+' or
modcargo='+QuotedStr('TITULAR')+' or modcargo='+QuotedStr('CONTRATADO')+')
order by nombre asc');
Prepare;
open;


while not eof do begin// e aqui el problema cuando pongo esto y se hace en un ciclo de 120 registro aproximado







////////////////
DataSource1.DataSet:=tabla.IBQHorasrep2;
dINI := DateTimePicker1.Date;
Dfin := DateTimePicker2.Date;
nDATO := (dINI + strtofloat('20'));
nDIAS := Trunc(dFIN - dINI);

with Tabla.IBQHorasrep2 do begin
sql.Clear;
Close;

FOR I := 0 TO nDIAS DO
BEGIN
nDATO := (dINI + STRTOFLOAT(INTTOSTR(I)));
dFECHA := FLOATTODATETIME(nDATO);
cFECHA := FormatDateTime('mm/dd/yyyy', dFECHA);
// SHOWMESSAGE(cFECHA);
// S := FormatDateTime('dddd, mmmm, yyyy, hh:mm AM/PM');

SQL.Add('select min(h.he),max(h.hs),CAST('+QuotedStr(cFECHA)+' AS DATE)
F1,p.nombre,p.apellido,p.cedula,h.fecha');
SQL.Add('from personal p left join horas h on h.cedula=p.cedula and h.fecha='+QuotedStr(cFECHA)+'');
SQL.Add('where p.cedula = :parcedula and p.status ='+QuotedStr('Activo')+'');
SQL.Add('group by p.cedula, p.nombre, p.apellido,h.fecha,3'); //
IF I < nDIAS THEN
BEGIN
SQL.Add(' UNION ');
END
ELSE
BEGIN
SQL.Add(' order by 3,1 ');
END


END;


Prepare;

ParamByName('parcedula').AsString:=tabla.IBQuerypersonalCEDULA.AsString;


Open;
end;




//////////////// end;


//*****ver foto

if tabla.IBQuerypersonalFOTO.IsNull then begin
Image1.Picture:=nil;
end else begin
if tabla.IBQuerypersonalFORMATOFOTO.AsString ='BMP' then
image1.Picture.Graphic:=TBitmap.Create

else if tabla.IBQuerypersonalFORMATOFOTO.AsString ='JPG' then
Image1.Picture.Graphic:=TJpegImage.Create


else

exit;
m:=tabla.IBQuerypersonal.CreateBlobStream(tabla.IBQuerypersonalFOTO,bmread);
Image1.Picture.Graphic.LoadFromStream(m);
m.Free;

end;
//********* ver foto





b:=b+1;
label4.Caption:= inttostr(b);



Boton := Application.MessageBox ('¿Está Seguro que Desea Imprimir este registro?',
'Print',MB_YESNO+MB_ICONQUESTION);
If Boton = ID_YES Then begin
//impresion

form20.QRLabel19.Caption:=DBEdit4.Text; //ubicacion

form20.QRLabel2.Caption:=DBEdit1.Text;//nombre
form20.QRLabel3.Caption:=DBEdit3.Text; //apellido
form20.QRLabel5.Caption:=DBEdit2.Text; //cargo

form20.QRLabel4.Caption:=tabla.IBQuerypersonalCEDULA.AsString; //cedula
Form20.QuickRep1.Prepare;



form20.QuickRep1.Print;
//impresion




end
Else begin
end;




tabla.IBQuerypersonal.next;
end;
tabla.IBQuerypersonal.first;


end; //*-966222






end;//del case


end;
end;/////////////////////

este codigo da perfecto, pero cuando lo ejecuto en un while do para que se haga 120 veces obvio que consume mucha memoria

roman
06-03-2007, 21:10:26
Pues hombre, si e un código que ya ni tú entiendes y te produce errores aquí y allá, ¿no sería más adecuado que lo revisaras con detalle para ver qué pasa? ¿O prefieres poner aquí el código para que nosotros te lo revisemos?

// Saludos

CarlosHernandez
06-03-2007, 21:21:22
ya lo coloque, y lo puse tal cual sin modificaciones....

xander
06-03-2007, 22:31:03
Solo por tirar una posibilidad:

donde tienes esta asignación:

ParamByName('parcedula').AsString:=tabla.IBQuerypersonalCEDULA.AsString;


primero pregunta si el objeto esta disponible porque de no estarlo ahi puede dar un access violation... ponle una condición antes:

if assigned(ParamByName('parcedula')) then
ParamByName('parcedula').AsString:=tabla.IBQuerypersonalCEDULA.AsString;


Aunque la verdad esta bastante mal planteado este procedimiento... en tu lugar trataria de hacer un Procedimiento Almacenado que hiciera todos esos calculos y solo me devolviera los datos que me interesan... siempre va a ser mas eficiente...

CarlosHernandez
06-03-2007, 22:42:30
es la asignacion de un paramatro, alli asigno el valos del parametro con el campo del registro de la consulta directamente, ibquerypersonal es un ibquery, le hago un select y de alli la asignacion, y lo tengo despues de la consulta sql,

if assigned(ParamByName('parcedula')) then
ParamByName('parcedula').AsString:=tabla.IBQuerypersonalCEDULA.AsString;
que funcion tiene eso??? como trabaja?

CarlosHernandez
06-03-2007, 22:45:50
Aunque la verdad esta bastante mal planteado este procedimiento... en tu lugar trataria de hacer un Procedimiento Almacenado que hiciera todos esos calculos y solo me devolviera los datos que me interesan... siempre va a ser mas eficiente...

nunca e echo un procedimiento almacenado...
como empiezo por lo menos.....?

xander
06-03-2007, 22:50:30
que funcion tiene eso??? como trabaja?

Eso tiene la función de verificar que realmente exista el parámetro en la consulta antes de querer asignarle un valor "a la brava"...

Si por alguna razón tu ciclo nunca agrega la linea de SQL que referencia a ese parámetro, al ejecutar esta linea te va a dar un precioso "Access Violation"...

Pero hasme caso... replantea lo que estas haciendo ahi como un stored procedure en la base de datos y te vas a evitar tambien que en un determinado momento la consulta se haga exageradamente grande, lo cual no es para nada deseado y además innecesario. Igual y así matas el error del Out Of Memory ese que muy probablemente se deba al tamaño de la consulta SQL que estas queriendo pasar.

CarlosHernandez
06-03-2007, 23:03:53
Pero hasme caso... replantea lo que estas haciendo ahi como un stored procedure en la base de datos .

uso firebird 1.5, bueno ya voy a tener el 2.0 voy a probarlo, y el ibexpert, por lo menos como empiezo ???? un manual o algo???? una vez lo intente sin exito por eso el codigo ese que puse

ContraVeneno
07-03-2007, 00:48:28
Pues hombre, si e un código que ya ni tú entiendes y te produce errores aquí y allá, ¿no sería más adecuado que lo revisaras con detalle para ver qué pasa? ¿O prefieres poner aquí el código para que nosotros te lo revisemos?

// Saludos
ya lo coloque, y lo puse tal cual sin modificaciones....

jeje, creo que ya te hace falta un nuevo detector de sarcasmo :D:D

CarlosHernandez
07-03-2007, 14:03:22
jeje, creo que ya te hace falta un nuevo detector de sarcasmo :D:D

ey contraveneno no lo hice con mala intencion ni con sarcasmo, aunque viendo bien lo que escribi pareciera que si.... Sorry je je :o