Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Increíble error el Delphi va muy rapido! (https://www.clubdelphi.com/foros/showthread.php?t=77884)

Gattaca 03-03-2012 11:35:54

Increíble error el Delphi va muy rapido!
 
Hola!

Tengo un increíble problema!!

Veran estoy leyendo un archivo binario a una velocidad creo que muy rapida, causandome el error "EAccessViolation", y la unica forma de solventarlo es agregando un "sleep(1)", haciendo que mi applicación valla más lenta!.

Esté es el loop principal llamado desde un menu para cargar el archivo.
La aplicación no dejo de darme errores, hasta que agregue el sleep antes de llamar a ReadItem()
Código Delphi [-]
      // Objects, walls, grounds, etc...
      for itemId := 100 to ItemCount - 100 do
      begin
        // con esta linea no me da error y carga más de 30000+ objetos del archivo binario
        // sin ella, me dá error!
        sleep(1);
        application.ProcessMessages;
        SetItem(itemId-100, ReadItem(itemId));
        //writeln(flogfile, 'Successfully readed Item #' + inttostr(itemId) + '.');

      end;

MI funcion ReadItem
Código Delphi [-]
function TDatFile.ReadItem(Id: UInt16): TItem;
var value: byte;
    return: TItem;
    spriteId: UInt16;
begin
  try
    while (value <> $FF) do
    begin

      value := ReadData.ReadByte();

      case value of
        $00:
          ReadData.ReadUInt16();
        $17, $20, $FF, $01, $02, $03, $04, $05, $06, $07, $08,
        $0B, $0C, $0D, $0E, $0F, $10, $11, $12,
        $13, $14, $15, $18, $1B, $1F, $1C
        : begin end;
        $09, $0A: begin ReadData.ReadUInt16(); end;
        $1A, $1D: begin ReadData.ReadUInt16(); end;
        $16, $19: begin ReadData.ReadUInt16(); ReadData.ReadUInt16(); end;
        $1E: begin ReadData.ReadUInt16(); end;
        else begin
          writeln(Flogfile, '   ERROR: Invalid Integer: ' + inttostr(value) + ' at item #' + inttostr(Id));
        end;
      end;

    end; // End flags

    return := TItem.Create;

    return.ID := Id;

    return.Width := ReadData.ReadByte();
    return.Height := ReadData.ReadByte();

    if (return.Width > 1) or (return.Height > 1) then
      return.CropImage := ReadData.ReadByte();

    return.Blendframes := ReadData.ReadByte();
    return.xRepeat := ReadData.ReadByte();
    return.yRepeat := ReadData.ReadByte();
    return.zRepeat := ReadData.ReadByte();
    return.Animations := ReadData.ReadByte();

    setLength(return.Sprites, return.SpritesCount);

    try
      for spriteId := 0 to return.SpritesCount - 1 do
      begin
        return.Sprites[spriteId] := ReadData.ReadUInt16();

        //writeln(flogfile, ' Readed Sprite #' + inttostr(return.Sprites[spriteid]));
      end;
    except
       on E : Exception do
      writeln(flogfile, ' CRITICAL ERROR AT OBJECT #' + inttostr(id) + ': '#13 + E.ClassName+' error raised, with message : '+E.Message);
    end;

  finally
    result := return;
  end;
  {except
    on E : Exception do
      writeln(flogfile, ' CRITICAL ERROR: '#13 + E.ClassName+' error raised, with message : '+E.Message);
  end; }
end;

Porfavor ayudenme, no tengo idea de que está mal en mi codigo para que me tire ese error!!

Usando Embarcadero Delphi XE2
Windows 7 x64 Home Premium
Tengo derechos de admin.

marcoszorrilla 03-03-2012 14:11:05

Generalmente en la documentación de los dispositivos viene la información incluso ejemplos de como leer y escribir en ellos si es que lo permiten.

Sospecho que el dispositivo tenga un tiempo de espera entre una y otra llamada y por eso la función Sleep te ha resuelto el problema. Si tienes el manual o puedes contactar con alguien de la empresa fabricante te resolverá la duda, lo digo porque en una ocasión tuve que llamar nada menos que a Austria y me enviaron una Dll y ejemplos de uso........

Un Saludo.

Héctor Randolph 03-03-2012 20:15:18

Probablemente el error se presenta al llamar la función ProcessMessages en intervalos tan reducidos de tiempo.
Te propongo espaciar las llamadas para que en lugar de hacerlo en cada ciclo se hagan cada 400 ciclos por poner un ejemplo, el número lo decides tu mismo.

Quedaría algo como esto:

Código Delphi [-]
   for itemId := 100 to ItemCount - 100 do
      begin
        // con esta linea no me da error y carga más de 30000+ objetos del archivo binario
        // sin ella, me dá error!
        //sleep(1);
         if itemId mod 400 = 0 then // Solamente se procesan los mensajes cada 400 ciclos
            application.ProcessMessages;
        SetItem(itemId-100, ReadItem(itemId));
        //writeln(flogfile, 'Successfully readed Item #' + inttostr(itemId) + '.');

      end;

Saludos

Delphius 03-03-2012 20:18:00

Hola,
El problema tal vez esté en la creación del objeto de la clase TItem que regresa la función.

A mi una vez haciendo un trabajo para la facultad me salía un AV y todo parecía correcto; las creaciones y liberaciones. Yo estaba trabajando en una lista, a la vieja escuela con punteros, y no veía algo malo. Si dejaba corriendo mi aplicación llegaba el momento en que saltaba el AV. Luego debugueando, y controlando a mano, para ver donde saltaba descubrí que en realidad el error estaba en que el recorrido sobre la lista y las instrucciones que hacía se ejecutaban tan rápido que no daba tiempo a que las reservas de memoria me creara los nodos.

Lo tuve que solucionar forzandole a que se tome un tiempo entre un New() y el uso de la variable.
Muy posiblemente lo tuyo será un caso similar.

Saludos,

Gattaca 04-03-2012 08:44:55

Cita:

Empezado por Delphius (Mensaje 426779)
Hola,
El problema tal vez esté en la creación del objeto de la clase TItem que regresa la función.

A mi una vez haciendo un trabajo para la facultad me salía un AV y todo parecía correcto; las creaciones y liberaciones. Yo estaba trabajando en una lista, a la vieja escuela con punteros, y no veía algo malo. Si dejaba corriendo mi aplicación llegaba el momento en que saltaba el AV. Luego debugueando, y controlando a mano, para ver donde saltaba descubrí que en realidad el error estaba en que el recorrido sobre la lista y las instrucciones que hacía se ejecutaban tan rápido que no daba tiempo a que las reservas de memoria me creara los nodos.

Lo tuve que solucionar forzandole a que se tome un tiempo entre un New() y el uso de la variable.
Muy posiblemente lo tuyo será un caso similar.

Saludos,

Hola,

Ciertamente debo decir que tu problema tiene mucha coherencía, y es igual al mio, usando la función New he podido arreglar el error, cargando todos los objetos binarios (+30000) en menos de 1 segundo!

:confused: Estoy sorprendido como, aunque el codigo esté correcto, el puede no funcionar correctamente, y aún no me explico ¿cómo?, pero supongo que tiene que ver con la memoria, ya que leer un archivo binario en un loop for puede funcionar radicalmente rapido, causando así que donde está alojada mi variable en la memoria, sea reescribida a cada ó borrada a cada momento, según DelphiBasics.co.uk, la palabra reservada New tiene está pequeña explicación;

Código:

New is used when the storage is requirement is fixed in size. Use GetMem to dictate the exact storage size allocated.
El ejemplo dado usaba pointers, y solo tube que reescribir mi clase TItem a un record y crear un punto en la memoria que siempre sea fijo, acá usando New supongo.

En fin, ahora mi codigo funciona correctamente, y ya veo el buen uso de New con respecto a las memorias :)

Pido perdon si mi explicación suena incoherente, pero soy muy joven y estoy muy metido en esto de la programación.

Muchas gracias nuevamente a todos, ayudandome desde el 2009 jejeje
Un saludo!


La franja horaria es GMT +2. Ahora son las 06:16: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