Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Problem mit Overflow (https://www.delphipraxis.net/35700-problem-mit-overflow.html)

DelphiFreund 10. Dez 2004 22:16


Problem mit Overflow
 
Hi,
ich weiss, dass das eine dumme Formulierung ist, aber mir ist nichts besseres eingefallen. Zum Problem: Wenn nun Byte1:= 180 und Byte2:= 90, und wenn ich diese addiere kommt glaub ich 15 raus, es gibt also einen Überlauf, kann ich irgendwie überprüfen ob es einen Overflow gibt oder bei der letzten Operation gab? Das würde alles wesentlich vereinfachen, bei Additionen. Vielen Dank für jede Resonanz.


Gruß DelphiFreund

jfheins 10. Dez 2004 22:19

Re: Problem mit Overflow
 
Du kannst irgendwo in den Tiefen des Compilers eine "Exeption bei Überlauf" bzw. "Überlaufprüfung" aktivieren ...

DelphiFreund 10. Dez 2004 22:20

Re: Problem mit Overflow
 
Klingt gut, ich mach mich auf die Suche.


Wer sucht wird fündig :) : Hier die direktiven: {$OVERFLOWCHECKS ON} oder {$OVERFLOWCHECKS OFF}

jfheins 10. Dez 2004 22:29

Re: Problem mit Overflow
 
Sonst:

Compilerbefehl:
Delphi-Quellcode:
{$Q+}

Puhbaehr 11. Aug 2006 17:16

Re: Problem mit Overflow
 
Und gleiches per Code abfangen/abfragen?

Pseudocode:
Code:
var Zahl : Byte;
...
Zahl := 200;
inc (Zahl, 100);
if (überlauf) then ...
Ich hab versucht mit dem Carry-Flag zu experimentieren.
Asm-Pseudocode:
Code:
function Carry : boolean; Register;
 asm
  push EAX

  jc @@C      // jump if carry
  jmp @@NC

  @@C:        // carry
  mov AL, 1
  jmp @@end

  @@NC:       // no-carry
  mov AL, 0

  @@end:
  mov Result, AL // mov Result

  pop EAX
 end;

...

Zahl := 200;
inc (Zahl, 100);
if (Carry) then ...
Funktioniert im genannten Beispiel. Funktioniert aber nicht nach z.B. GetFileSize :gruebel:
Reicht das Carry-Flag um auf einen Überlauf zu prüfen?

Muetze1 11. Aug 2006 17:18

Re: Problem mit Overflow
 
Dafür gibt es das Overflow Flag.

Mach den Compilerschalter an und rechne es in Delphi innerhalb eines Try/Except Blockes. Wenn es eine EOverflow Exception gibt, dann ist ein Überlauf aufgetreten.

brechi 11. Aug 2006 18:08

Re: Problem mit Overflow
 
Delphi-Quellcode:
function Carry : boolean;
asm
  db 0d6h
end;

Puhbaehr 11. Aug 2006 18:40

Re: Problem mit Overflow
 
Über einen try/except-Block wollte ich es nicht machen sondern über eine einfache Funktion.

Brechis Beispiel funktioniert soweit. Nur was passiert hier? Meine Asm-Referenz gibt zu db nicht viel her. Und das was es hergibt ist wohl das falsche (define byte - reserviert ein Byte an Speicherplatz im Programm... Buch Assembler Ge-packt) :gruebel:

Vielen Dank 4 Help :)

Edit: Delphi zaubert aus db 0D6h db 1. Warum?

Hawkeye219 11. Aug 2006 19:53

Re: Problem mit Overflow
 
Hallo,

auf den korrekten Zustand des Overflow- oder Carry-Flags nach einer Addition zweier Bytes würde ich mich nicht verlassen. Die Addition wird häufig - nach einer Erweiterung der Operanden auf 32 Bit - durch eine 32-Bit-Addition oder einen LEA-Befehl durchgeführt. In diesen Fällen besitzen die genannten Flags keine Aussagekraft.

Gruß Hawkeye

Puhbaehr 11. Aug 2006 20:41

Re: Problem mit Overflow
 
Genau das habe ich gemerkt, nachdem die Funktion GetFileSize ausgeführt wurde.
...
Wie kann ich sonst mit einer einfachen Funktion den Überlauf prüfen? Wenns geht ohne einem Try/Exception-Block.
Oder frage ich mal anders, was genau macht der Try-Except-Block bei einem Überlauf? Wie überprüft er diesen?
:|

Muetze1 11. Aug 2006 21:03

Re: Problem mit Overflow
 
Liste der Anhänge anzeigen (Anzahl: 1)
Der Try/Except Block überprüft gar nix sondern kommt einfach nur zur Ausführung, wenn eine Exception auftritt.

So, ich habe mir das ganze mal angeschaut und musste feststellen, das die Überlaufprüfung nicht wirksam ist, wenn man Bytes addiert. Dadurch das die 32 Bit Register nutzt, wird das Overflow Flag nicht gesetzt, da auch 32-bittig addiert wird. Wenn aber nun die Bereichsprüfung mit eingeschaltet ist, dann überprüft er danach das Ergebnis, ob es kleiner gleich 255 ist und somit in ein Byte passt. Ist dies nicht der Fall, dann schmeisst er die ERangeError Exception.

Im Anhang ein Bild vom erzeugten Code beim addieren von 2 Bytes zu einem 3. Byte mit Überlauf. Man sieht gut den Sprung bei gesetztem Overflow Flag (jno), die Begrenzung der Werte vor der Addition (and xxx, $00ff) und den Sprung bei Werten kleiner gleich 255 über die BoundError Auslösung.

Puhbaehr 11. Aug 2006 21:26

Re: Problem mit Overflow
 
Hmm na dann werd ich doch mal den Weg der Überlaufprüfung über dem Try/Exception-Block gehen und testen.
Du sprichst im Moment von Byte und, dass das Overflow-Flag nicht anspringt sobald es einen Überlauf gibt. Der Typ Byte war in meinem Fall hier nur ein Beispiel. Die Überlaufprüfung benötige ich beim Typ Cardinal. Da zeigte das Flag Wirkung als ich zweimal 4000000000 zur Zahl hinzu addierte.
Ich möchte, um konkret zu werden, die Dateigröße auslesen und die in einem Cardinal speichern. Da der Typ Cardinal keine Dateigrößen über 4 GB Speichern kann hatte ich vor hier auf Überlauf zu prüfen für den Fall, dass Dateien über 4 GB ausgewählt werden was bei den heutigen Festplatten und Datenmengen ohne weiteres passieren kann.

Vielen Dank auf jeden Fall bis hier her.

Muetze1 11. Aug 2006 21:43

Re: Problem mit Overflow
 
Ok, dann gibt es ja einen Weg für dich. Aber warum nutzt du nicht einfach den Typ Int64 für die Dateigrösse? Den Overflow Check kannst du dort ja dann trotzdem noch machen, falls die Datei halt grösser ist...

Puhbaehr 11. Aug 2006 22:38

Re: Problem mit Overflow
 
Langsam langsam. Im Moment bin ich froh, wenn ich es schaffe 4 GB große Dateien fehlerfrei zu laden und zu verarbeiten. Mehr zu laden ist im Moment auch nicht beabsichtigt und notwendig. Im Gegenteil.
Wenn ich mit all dem hier fertig bin dann können wir evtl. darüber reden Dateien zu laden die größer sind als 16 ZB (ZettaByte; 17179869184 GigaByte) MUHA LOL nein ehrlich das reicht erstmal ;) Danke

Muetze1 12. Aug 2006 00:11

Re: Problem mit Overflow
 
Es geht mir ja nicht um's Laden, das kannst du ja auch weiterhin auf 4 GB beschränken, sondern darum, dass du keine Arbeit der Variable machen brauchst, in der du die Dateigrösse ablegst.

Puhbaehr 12. Aug 2006 14:22

Re: Problem mit Overflow
 
Muuuh hätt ich jetzt fast gesagt.

Habe den Try-Exception-Block erst um die gesamten Anweisungen gelegt. Nachdem das nicht funzte hab ich ihn direkt um die betreffende Stelle gesetzt.
Delphi-Quellcode:
var
  FileSize: dword;
  i : Byte;
...

{$Q+}  // Überlaufprüfung aktiviert
{$R+}  // Bereichsprüfung aktiviert

FileSize := GetFileSize (FileName, nil);

for i := 0 to 255 do
 begin
  try
    FileSize := FileSize + FileSize;
  except
    on EOverflow do   // Überlaufprüfung für Gleitkommazahlen
     begin
      SetLastError (E_FILESIZE_TO_LARGE);
     end;
    on EIntOverflow do   // Überlaufprüfung für Ganzzahlen
     begin
      SetLastError (E_FILESIZE_TO_LARGE);
     end;
    on ERangeError do   // Bereichsprüfung
     begin
      SetLastError (E_FILESIZE_TO_LARGE);
     end;
    else
      SetLastError (E_FILESIZE_TO_LARGE);
     end;
   end;
Irgendwas hab ich/ist falsch. Die Überlauf- und Bereichsprüfung ist aktiviert. :wiejetzt: Was fehlt mir? :gruebel:

Muetze1 12. Aug 2006 15:04

Re: Problem mit Overflow
 
SetLastError setzt nur den Result Code der WinAPI - aber was erwartest du denn noch dazu? So lange keiner dieses Flag auswertet passiert nix weiter. Du könntest z.B. eine Exception auslösen nach dem SetLastError() mit
Delphi-Quellcode:
 RaiseLastOSError;
bzw. früher
Delphi-Quellcode:
RaiseLastWin32Error;
.

Puhbaehr 12. Aug 2006 16:53

Re: Problem mit Overflow
 
Ich wartete darauf, dass beim Überlauf eine Exception ausgelöst wird. Das passiert aber nicht.
...
Ne du, jetzt machen wir erstmal Pause. Für heut ist Feierabend. Nächste Woche gehts weiter :)

Schönes Wochende :) Bis dann


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:19 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz