Hallo zusammen, ich möchte Integer-overflows mittels Exceptions behandeln. Um ein Beispiel zu geben: Es sollen zwei Zahlen multipliziert werden, diese beiden Zahlen werden mittels cin in zwei Integer-Variablen a und b eingelesen, das Ergebnis in die Variable c. Wenn eine Eingabe dazu führt, dass eine Variable überläuft soll es mittels Ausnahme erkannt werden und eine Fehlermeldung ausgegeben werden. Wie könnte das als Code aussehen?
In Ordnung, kann man sonst wie erkennen wann eine Variable überläuft? Vielleicht irgendwie in Verbindung mit narrow_cast? Ich könnte ja die Variablen als double-typen deklarieren und dann eine Konvertierung in int mittels narrow_cast vornehmen. Oder bin ich da auf dem Holzweg.
edelhannes schrieb: > In Ordnung, kann man sonst wie erkennen wann eine Variable überläuft? rechnet mit bigint, wenn der Ergebnis > max_int ist dann würde es überlaufen.
Google zeigt diverse Resultate wie man eine Multiplikation auf Überlauf prüft. Es gibt keine direkte/einfache Methode. Nimm eine der zu findenden Varianten und füge den Exception-Code hinzu. narrow_cast gibts im C++ Standard nicht. Nach double konvertieren ist immer gefährlich, da kann man ggf. Präzision verlieren.
Muss die Erklärung denn in Deutsch sein? Wenn nicht dann findet man ja reichlich Hinweise, denn so ungewöhnlich ist die Frage ja nicht. Etwa https://stackoverflow.com/questions/199333/how-to-detect-integer-overflow
Stefan S. schrieb: > Muss die Erklärung denn in Deutsch sein? nein natürlich nicht :-) Danke für den Link Peter II schrieb: > rechnet mit bigint, wenn der Ergebnis > max_int ist dann würde es > überlaufen. Das ist ja schon fast zu einfach.
Dr. Sommer schrieb: > Es gibt keine direkte/einfache Methode. Das ist eigentlich die Info die ich brauche, das wusste ich nicht.
edelhannes schrieb: > Das ist eigentlich die Info die ich brauche, das wusste ich nicht. Die einfachste Lösung wird sein, das du keine Werte eingibst die einen Überlauf erzeugen, damit nimmst du dem Computer auch noch Denkarbeit ab, das kann der Mensch ohnehin besser.
Schreib Dir ne eigene Klasse, die das macht. Das Verhalten der prim. DT ist vorgegeben. Willst Du was anderes ... mach es selbst.
Scott Meyers schrieb: > Schreib Dir ne eigene Klasse, die das macht. Ich glaub darauf wär er schon gekommen. Nur weil man etwas in eine Klasse verpackt, kann es nicht plötzlich kniffelige Berechnungen durchführen. Die Frage war, wie man Overflows erkennt, was portabel/standardkonform nicht offensichtlich ist.
Dr. Sommer schrieb: > Scott Meyers schrieb: >> Schreib Dir ne eigene Klasse, die das macht. > Ich glaub darauf wär er schon gekommen. Nur weil man etwas in eine > Klasse verpackt, kann es nicht plötzlich kniffelige Berechnungen > durchführen. das war auch nicht die Behauptung. Trotzdem ist es möglich! > Die Frage war, wie man Overflows erkennt, was > portabel/standardkonform nicht offensichtlich ist.
Cyberpunk schrieb: > Ist Inline-Assembler keine zulässige Lösung? Um den Status des overflow-Flags zu sehen? Keine Ahnung wie man das macht..
Cyberpunk schrieb: > Ist Inline-Assembler keine zulässige Lösung? wenn es Plattform unabhängig sein soll. NEIN
edelhannes schrieb: > Um den Status des overflow-Flags zu sehen? Keine Ahnung wie man das > macht.. Also z.B. beim ARMv7M wird das Carry Flag überhaupt nicht bei der Multiplikation gesetzt. Das bringts also nicht so wirklich...
edelhannes schrieb: > Cyberpunk schrieb: >> Ist Inline-Assembler keine zulässige Lösung? > > Um den Status des overflow-Flags zu sehen? Keine Ahnung wie man das > macht.. Je nach Architektur gibt's in Assembler ggf. gar keinen Overflow bei Multiplikationen, weil das Ergebnis nicht auf die gleiche Größe gezwungen wird, wie die Operanden. So ist es beispielsweise bei x86 und beim AVR.
Ich habe schnell eine Klasse dafür erstellt, ist im Anhang zu finden. Es können sich durchaus noch kleinere Fehler darin befinden, und es findet damit keine Integer Promotion statt, scheint aber mehr oder weniger zu funktionieren.
Daniel A. schrieb: > Es > können sich durchaus noch kleinere Fehler darin befinden Leider ja: 1. Der Overflow von signed Zahlen ist undefiniertes Verhalten, somit kann z.B. der if-Block im + Operator wegoptimiert werden und die Exception wird ggf. nie ausgelöst. Das lässt sich reparieren, indem man vor der Operation den Bereich prüft. std::numeric_limits<T>::max()/min() hilft dabei. 2. Statt der C-Casts (T)... würde ich lieber static_cast<T> (...) nutzen. 3. Ich würde mit static_assert sicherstellen ob T/U überhaupt Zahlen sind. 4.
1 | template<typename U> |
2 | OverflowCheckingNumber( U y ){ |
3 | if( y != (U)(T)y ) |
Das greift leider nicht (immer). Wenn man z.B. Signed->unsigned->signed castet, kann sehr wohl das gleiche rauskommen, obwohl die Zahl nicht als "unsigned" darstellbar ist. Hier braucht man Overloads um alle Spezialfälle abzudecken... 5.
1 | template<typename U> operator U() const; |
Das halte ich für ziemlich gefährlich - ein Typ der in alles umwandelbar ist! Da würde ich lieber eine Funktion für nehmen. 6. Man könnte noch großzügig "constexpr" verteilen. 7. Ich würde noch Vergleichsoperatoren sowie Copy/Move-Konstruktoren einbauen.
Dr. Sommer schrieb: > 5.template<typename U> operator U() const;Das halte ich für ziemlich > gefährlich - ein Typ der in alles umwandelbar > ist! Nö, nur in das, wohin auch T implizit konvertiert werden kann.
Rolf M. schrieb: > Nö, nur in das, wohin auch T implizit konvertiert werden kann. Achja, okay weil bei der Rückgabe kein cast ist. Man könnte es noch etwas aufhübschen:
1 | #include <type_traits> |
2 | #include <utility> |
3 | |
4 | template<typename U, class X = typename std::enable_if<std::is_convertible<T, U>::value>::type> |
5 | operator U() const { ... |
So gibts etwas nettere Fehlermeldungen und man könnte es überladen falls nötig.
Beitrag #5157268 wurde vom Autor gelöscht.
Hier nochmal eine neue Version, mit ein paar Bugfixes. Sorry wegen dem letzten von mir gelöschten Beitrag, mir ist im letzten Moment noch ein Fehler aufgefallen.
Daniel A. schrieb: > Hier nochmal eine neue Version Wow ich bin eigentlich noch nicht so fortgeschritten, dass ich im ganzen verstehe was da gemacht wird. Danke trotzdem für deine Mühe, ich werde wohl etwas simpleres ausprobieren müssen. Ich habe erst die Grundlagen von C++ durch, d.h. alles bis simple Klassen.
Mal einfach ausgedrückt: Diese Überlauf-Erkennungs-Operationen "sehen" für den Compiler teilweise sinnlos aus und sie werden mitunter wegoptimiert. Da gibt es endlose Feinheiten zu beachten. Ganz viele Sicherheitslücken in Software basieren exakt darauf, dass jemand Überläufe nicht oder nicht korrekt abfängt. Da könnte man ganze Bücher drüber schreiben. In Bereichen, wo Softwarefehler Menschen verletzen oder gar töten könnten (Flugzeug, ...) werden deshalb gerne Sprachen verwendet, die Überlauf von Haus aus erkennen und behandeln. C kommt natürlich auch vor, aber der Output vom Compiler wird intensiv getestet. Siehe auch hier für einen kleinen Einstieg: http://www.fefe.de/intof.html
Jochen schrieb: > Ganz viele > Sicherheitslücken in Software basieren exakt darauf, dass jemand > Überläufe nicht oder nicht korrekt abfängt. dabei geht es aber um Speicherüberläufe, das hat nur indirekt etwas damit zu tun.
Beitrag #5158343 wurde von einem Moderator gelöscht.
Peter II schrieb: > dabei geht es aber um Speicherüberläufe, das hat nur indirekt etwas > damit zu tun. Das eine hat nicht immer, aber oft direkt mit dem anderen zu tun. Im Link oben ist ein schönes Beispiel aus einer älteren Version von libiberty:
1 | if (*p == '*') |
2 | { |
3 | ++p; |
4 | total_width += abs (va_arg (ap, int)); |
5 | } |
total_width könnte überlaufen, da keine Prüfung implementiert ist. Nach Addition eines positiven Wertes wird total_width also kleiner. Als folge wird zu wenig Speicher reserviert -> Speicherüberlauf. Außerdem kann abs(...) auch negativ werden, mit gleicher Folge wie oben. Dazu braucht man nur INT_MIN als Argument übergeben, was im obigen Beispiel durch Benutzereingabe möglich ist.
Beitrag #5158677 wurde von einem Moderator gelöscht.
Beitrag #5158736 wurde von einem Moderator gelöscht.
Beitrag #5159283 wurde von einem Moderator gelöscht.
Beitrag #5159536 wurde von einem Moderator gelöscht.
Beitrag #5160088 wurde von einem Moderator gelöscht.
Beitrag #5160644 wurde von einem Moderator gelöscht.
Beitrag #5161267 wurde von einem Moderator gelöscht.
Beitrag #5161590 wurde von einem Moderator gelöscht.
Beitrag #5162002 wurde von einem Moderator gelöscht.
Beitrag #5162547 wurde von einem Moderator gelöscht.
Beitrag #5162639 wurde von einem Moderator gelöscht.
Beitrag #5165579 wurde von einem Moderator gelöscht.
Beitrag #5165591 wurde von einem Moderator gelöscht.
Beitrag #5165594 wurde von einem Moderator gelöscht.
Beitrag #5165596 wurde von einem Moderator gelöscht.
Beitrag #5165702 wurde von einem Moderator gelöscht.
Such mal nach safeint bei codeplex ist von microsoft
Beitrag #5165823 wurde von einem Moderator gelöscht.
Beitrag #5166146 wurde von einem Moderator gelöscht.
Beitrag #5166161 wurde von einem Moderator gelöscht.
Jochen schrieb: > Diese Überlauf-Erkennungs-Operationen "sehen" > für den Compiler teilweise sinnlos aus und sie werden mitunter > wegoptimiert. Das ist aber dann ein Fehler im Compiler. Der Compiler darf sie natürlich wegoptimieren, wenn sie tatsächlich sinnlos sind, denn dann tritt ja auch kein Überlauf auf. Aber das muss er auch garantieren. Es gab ähnliche Diskussionen, als GCC angefangen hat, scharf zu optimieren und die Tests gegen Pufferüberläufe wegzuoptimieren. Das haben die ganz schnell wieder sein gelassen... Daniel A. schrieb: > Hier nochmal eine neue Version, mit ein paar Bugfixes. Sorry wegen dem > letzten von mir gelöschten Beitrag, mir ist im letzten Moment noch ein > Fehler aufgefallen. Deine Klasse krankt an genau dem o.g. Problem: Du führst einfach die Berechnung aus und guckst hinterher, ob das Ergebnis korrekt ist, indem du zurückrechnest. Ein Überlauf bei signed int ist aber nicht nur unschön, sondern auch undefined behaviour! D.h., der Compiler dürfte das alles wegoptimieren und durch exit(0) ersetzen... Mehr dazu: https://www.securecoding.cert.org/confluence/display/c/INT31-C.+Ensure+that+integer+conversions+do+not+result+in+lost+or+misinterpreted+data
Beitrag #5167762 wurde von einem Moderator gelöscht.
Beitrag #5167781 wurde von einem Moderator gelöscht.
Beitrag #5167790 wurde von einem Moderator gelöscht.
Beitrag #5167794 wurde von einem Moderator gelöscht.
Beitrag #5167801 wurde von einem Moderator gelöscht.
Beitrag #5167803 wurde von einem Moderator gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.