C++ Verhalten einer double Funktion im Fehlerfall testen

@asdfman: Du hast recht, das war tatsächlich ein ungünstiges Beispiel.
Was aber deine Erweiterung angeht:
Code:
cat main.cpp;clang++ -std=c++11 -O3 main.cpp;echo ==============; ./a.out 
#include <iostream>

double test(int id) {
        if(id < 0) {
                double *a = nullptr;
                double c = *a;
                return c;
        } else {
                return 1.0;
        }
}

int main() {
        double a = test(-1);
        std::cout << a << std::endl;
}
==============
0 //<- kein Segfault
(clang 3.5 auf fedora 22)
Clang ist bei mir jetzt aber auch der einzige Compiler, der sich so verhält. Das ist ja gerade das Porblem mit UB. Auch wenn es sich bei noch so vielen Tests so verhält wie erwartet kann man sich nicht darauf verlassen, dass das immer der Fall ist (sofern die Compilerdokumentation nichts anderes sagt).

Wie dem auch sei, ich glaube wir sind uns alle einig, dass das nicht die geeignete Art und Weise ist um Fehleingaben zu melden und daher hier meine Meinung zum eigentlichen Topic:

Ich vermute mal, dass deine Klasse einen mathematischen Vektor darstellen soll und damit ist ein out-of-bounds-access ein ganz klarer Programmierfehler. In den meisten Fällen sollte die Größe sogar zur Compilezeit bekannt sein. Ergo würde ich hier entweder eine Exception werfen oder sogar ganz auf eine reguläre Laufzeitüberprüfung verzichten und lediglich fürs Debuggen ein paar asserts einbauen. Also entweder

Code:
double Vektor::get(int index) const {
	if (index < 0 || index >= mSize) {
		throw std::invalid_argument("ERROR: index does not exist.");
	}
	return mWerte[index]; // Wert zurückgeben	
}
oder
Code:
double Vektor::get(int index) const {
	assert(index >= 0);
	assert(index < mSize);
	
	return mWerte[index]; // Wert zurückgeben	
}

Das steht auch im Einklang mit dem Verhalten von Standardcontainern: Ein std::vector::at wirft übrigens auch eine Exception, während std::vector::operator[] aus Performancegründen überhauptnicht auf Fehleingaben testet.

Die ganzen Varianten mit der Rückgabe von bools oder ungültigen Werten sind meiner Meinung nur dann sinnvoll, wenn auch bei korrekter Programmausführung und mit korrekten/erwarteten Eingabedaten damit gerechnet werden muss, dass kein gültiger Wert zurückgeliefert werden kann. Typische Beispiele sind das parsen von strings oder ein Verbindungsaufbau zu einem Ziel im Netzwerk/Internet.
 
Zuletzt bearbeitet:
Miuwa: Ich konnte das mit clang so reproduzieren. Vielen Dank dafür. Werde mir nach der Arbeit mal ansehen, welcher Code da generiert wurde.

Und bei der Gelegenheit muss ich natürlich auch antred sagen, dass ich mich getäuscht habe und werde diese Behauptung nicht weiter vertreten.
 
Miuwa schrieb:
Die ganzen Varianten mit der Rückgabe von bools oder ungültigen Werten sind meiner Meinung nur dann sinnvoll, wenn auch bei korrekter Programmausführung und mit korrekten/erwarteten Eingabedaten damit gerechnet werden muss, dass kein gültiger Wert zurückgeliefert werden kann. Typische Beispiele sind das parsen von strings oder ein Verbindungsaufbau zu einem Ziel im Netzwerk/Internet.

Sehe ich auch so. Fälle, die bei korrekter Programmausführung nie auftreten, sollten lediglich mit asserts abgedeckt werden und nicht mit irgendwelchen Fehlercodes oder Exceptions. Gerade als Anfänger muss man etwas aufpassen, dass man nicht "zu vorsichtig" programmiert und überall Exceptions/Fehlercodes einbaut, wo diese gar nicht nötig wären. Falls den Fragesteller die Theorie etwas interessiert: https://en.wikipedia.org/wiki/Design_by_contract

Einfach gesagt verlangst du einfach von einem Programmierer, der deine Vektorklasse verwendet, dass er die korrekt verwendet, sprich nicht auf Elemente ausserhalb des gültigen Bereichs zugreift. Falls er dies dennoch tut, wird das mit einer assertion abgefangen und das Programm beendet. Die Vektorklasse hat nicht die Verantwortung, mit diesen Fehlern sinnvoll umgehen zu können.
 
Zuletzt bearbeitet:
Seppel08 schrieb:
-NAN ist bei mir irgendwie nicht definiert, obwohl ich <cmath> included hab.

Weiß einer, warum das bei mir nicht definiert sein könnte?
 
Seppel08 schrieb:
Weiß einer, warum das bei mir nicht definiert sein könnte?

Weil der C und C++ Standard "nur" vorgibt, dass es Fließkommatypen gibt, die Implementierung aber frei lässt. Somit könnte jeder Compiler seine eigene Float-Implementierung haben und es gibt kein sprachglobales NAN.
Irgendwann wurden aber die Marcros mehr oder weniger vordefiniert - glaube in C mit C99, C++ weis ich gerade nicht. Sprich wenn ein Compiler NAN's unterstützt, so kann er das Macro eben nutzten. Werden NAN's nicht unterstütz ist definiert, dass das Macro eben nicht definiert ist.
Das ganze kann man hier auch nochmal etwas nachlesen.
 
TrebuTurbo schrieb:
Weil der C und C++ Standard "nur" vorgibt, dass es Fließkommatypen gibt, die Implementierung aber frei lässt. Somit könnte jeder Compiler seine eigene Float-Implementierung haben und es gibt kein sprachglobales NAN.
Irgendwann wurden aber die Marcros mehr oder weniger vordefiniert - glaube in C mit C99, C++ weis ich gerade nicht. Sprich wenn ein Compiler NAN's unterstützt, so kann er das Macro eben nutzten. Werden NAN's nicht unterstütz ist definiert, dass das Macro eben nicht definiert ist.
Das ganze kann man hier auch nochmal etwas nachlesen.

Heißt dass, wenn es bei mir nicht definiert ist, hab ich Pech gehabt?
 
Hab jetzt Visual Studio geupdatet (Der Standard Compiler der 2012er Version kannte das nicht :freak:). Jetzt geht's :). Dann mach ich es mit NAN, ist die einfachste Methode. Aber die anderen Ideen sind auch nicht schlecht :D.
 
Was mir mit dem NAN gerade in den Sinn kommt. Das funktioniert ja nur, wenn du weißt, dass von deinem Programm niemals ein NAN in den Vektor bei Index abgelegt werden wird. Kann das Programm von sich aus ein NAN als gültiges Ergebnis einer Berechnung ablegen, kann man bei der Abfrage nicht mehr entscheiden, ob nun der Index außerhalb des Intervalls ist.
 
Microarchitekt schrieb:
Was mir mit dem NAN gerade in den Sinn kommt. Das funktioniert ja nur, wenn du weißt, dass von deinem Programm niemals ein NAN in den Vektor bei Index abgelegt werden wird. Kann das Programm von sich aus ein NAN als gültiges Ergebnis einer Berechnung ablegen, kann man bei der Abfrage nicht mehr entscheiden, ob nun der Index außerhalb des Intervalls ist.

Das hab ich so geregelt, dass NAN nicht gesetzt werden kann.
 
Zurück
Oben