Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   error.. out of memory... (https://www.clubdelphi.com/foros/showthread.php?t=41053)

CarlosHernandez 06-03-2007 19:38:37

error.. out of memory...
 
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..

Código Delphi [-]
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

codigo
 
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


Código Delphi [-]
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:
Código Delphi [-]
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:
Código Delphi [-]
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,

Código Delphi [-]
if assigned(ParamByName('parcedula')) then
ParamByName('parcedula').AsString:=tabla.IBQuerypersonalCEDULA.AsString;
que funcion tiene eso??? como trabaja?

CarlosHernandez 06-03-2007 22:45:50

Cita:

Empezado por xander
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

Cita:

Empezado por CarlosHernandez
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

Cita:

Empezado por xander
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

Cita:

Empezado por roman
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

Cita:

Empezado por CarlosHernandez
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

Cita:

Empezado por ContraVeneno
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


La franja horaria es GMT +2. Ahora son las 06:36:55.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi