![]() |
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 |
Re: Problem mit Overflow
Du kannst irgendwo in den Tiefen des Compilers eine "Exeption bei Überlauf" bzw. "Überlaufprüfung" aktivieren ...
|
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} |
Re: Problem mit Overflow
Sonst:
Compilerbefehl:
Delphi-Quellcode:
{$Q+}
|
Re: Problem mit Overflow
Und gleiches per Code abfangen/abfragen?
Pseudocode:
Code:
Ich hab versucht mit dem Carry-Flag zu experimentieren.
var Zahl : Byte;
... Zahl := 200; inc (Zahl, 100); if (überlauf) then ... Asm-Pseudocode:
Code:
Funktioniert im genannten Beispiel. Funktioniert aber nicht nach z.B. GetFileSize :gruebel:
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 ... Reicht das Carry-Flag um auf einen Überlauf zu prüfen? |
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. |
Re: Problem mit Overflow
Delphi-Quellcode:
function Carry : boolean;
asm db 0d6h end; |
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? |
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 |
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? :| |
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. |
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. |
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...
|
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 |
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.
|
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:
Irgendwas hab ich/ist falsch. Die Überlauf- und Bereichsprüfung ist aktiviert. :wiejetzt: Was fehlt mir? :gruebel:
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; |
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:
bzw. früher
RaiseLastOSError;
Delphi-Quellcode:
.
RaiseLastWin32Error;
|
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 18:59 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