wieso gibt es in c++ kein finally?
-
absturz-freak schrieb:
hä??? schrieb:
Wenn man könnte, was würde dann finally neues bringen, was du sonst nicht kannst?
na, RAII funzt z.b. nicht mehr bei einem (int)0 = ...;
das programm kackt gnadenlos ab. ein finally könnte dann noch ein paar aufräumarbeiten verrichten.Jeder Destruktor dann aber auch
aber wie gesagt, es liegt ja nicht am fehlenden finally, sondern an den exceptions, die zu 'high-levelig' sind.

eben
C++ hat doch eigentlich ein eingebautes finally bei jedem "}" (wenn man mal die Heap Sachen außer Acht lässt, da muss man dann auto_ptr oder sowas nehmen). Das "C++ finally" ruft dann die Destruktoren auf. Alles was du einmal in C++ in nen Destruktor schreibst, musst du in allen finallys immer wieder hinschreiben -> code duplication
-
Im Borland C++ Builder gibt es das __finally. Und ehrlich gesagt möchte ich nicht mehr darauf verzichten.
Ich empfinde es als sehr angenehm, Aufräumarbeiten nur im __finally-Block machen zu können und nicht im catch-Block für den Fehlerfall und zusätzlich am Funktionsende den, meist zu 95 Prozent indentischen, Code nochmal hinkopieren zu müssen.
-
Joe_M. schrieb:
Ich empfinde es als sehr angenehm, Aufräumarbeiten nur im __finally-Block machen zu können und nicht im catch-Block für den Fehlerfall und zusätzlich am Funktionsende den, meist zu 95 Prozent indentischen, Code nochmal hinkopieren zu müssen.
-
@Joe
Ich habe das ursprünglich auch so gehandhabt (nutze ebenfalls BCB). Mittlerweise nutze ich aber durchgängig Smartpointer und passende Destruktoren, so dass finally nicht mehr nötig ist.
-
Konrad Rudolph schrieb:
Das trifft leider heutzutage noch immer auf viele C++ Entwickler zu, gerade wenn diese vor dem C++98 Standard angefangen haben, aber auch wenn sie von eben jenen gelernt haben. (etwas überzogen) So wie es noch immer Firmen gibt bei denen böse gesprochen alles Verboten ist, das der Chefentwickler nicht versteht...
cu André
-
Ja, RAII ist toll.
Finally wäre trotzdem nett.
-
hustbaer schrieb:
C++ ist doch sonst nicht so zimperlich wenns darum geht mehrere Wege anzubieten um dasselbe Ziel zu erreichen.
Naja, das kommt eher durch die Abwärtskompatibilität. finally ist ein strukturierter Ansatz, das passt nicht wirklich zu OO.
exception-freak schrieb:
naja, aber wenn man mit c++ exceptions noch nicht mal 'nen nullpointer-access oder eine miese rechenoperation wie 'division durch 0' abfangen kann, macht das auch nicht viel sinn.
Genau das wäre imo brauchbarer für den neuen Standard als finally. Sowas lässt sich mit C++ bisher leider nur plattformspezifisch umsetzen.
-
hustbaer schrieb:
Finally wäre trotzdem nett.
Finally ist in C++ total überflüssig.
-
groovemaster schrieb:
exception-freak schrieb:
naja, aber wenn man mit c++ exceptions noch nicht mal 'nen nullpointer-access oder eine miese rechenoperation wie 'division durch 0' abfangen kann, macht das auch nicht viel sinn.
Genau das wäre imo brauchbarer für den neuen Standard als finally. Sowas lässt sich mit C++ bisher leider nur plattformspezifisch umsetzen.
Hmm,
Null-Pointer-Exceptions lassen sich simpel mit einer "Checked Access" Funtion durchführen, oder alternativ mit einer entsprechenden Template-Klasse die das etwas schöner macht:#include <iostream> #include <exception> template<typename T> T* checked_access(T* ptr) { if(!ptr) { throw std::runtime_error("Zero pointer exception"); } return ptr; } int main() { int* a = NULL; try { *checked_access(a) = 3; } catch(...) { //... } return 0; };Bei einer Division ist es immer sinnvoller, den Divisor auf 0 zu prüfen, als solche Fehler über ein Laufzeitfehlersystem einmal quer durchs Betriebssystem zu schießen.
Beides ist Plattformunabhängig...
-
Das Problem ist sowohl bei Null-Pointer wie Div durch 0, daß man das jeweils von Hand vor dem Zugriff überprüfen muß. Es wäre schöner, wenn die Laufzeitumgebung automatisch eine entsprechende Exception werfen würde.
-
~john schrieb:
Es wäre schöner, wenn die Laufzeitumgebung automatisch eine entsprechende Exception werfen würde.
Bitte behaltet immer in Hinterkopf das C++ auch das Ziel hat effizient und schnell zu sein. Bei C++ wird nicht ohne grund einiges von Laufzeitentscheidungen in die Hand des Entwicklers gelegt. Wenn ich z.B. ausschließen kann das ich über die Indexe eines vectors zugreife, ist eine Prüfung eine unnötige Laufzeitbelastung. Ebenso wenn ich von vorne herein weiß das keine 0 in meinen Divisionen auftreten kann oder, oder, oder...
Man muss abwägen zwischen Sicherheit und Performance, C++ hat halt auch letzteres im Auge. Wobei übertriebene Sicherheit wiederum dazu führt das Entwickler Fehler teilweise garnicht betrachten.
cu André
-
asc schrieb:
Bitte behaltet immer in Hinterkopf das C++ auch das Ziel hat effizient und schnell zu sein. Bei C++ wird nicht ohne grund einiges von Laufzeitentscheidungen in die Hand des Entwicklers gelegt. Wenn ich z.B. ausschließen kann das ich über die Indexe eines vectors zugreife, ist eine Prüfung eine unnötige Laufzeitbelastung.
nö, es muss ja nix ständig überprüft werden. eine aktion ist nur gefragt, wenn etwas passiert ist. bisher wird x/0 vom OS ausgewertet, das eine hässliche messagebox aufmacht (falls die exception nicht behandelt wird). sie könnte aber genauso gut an die c++ runtime library weitergereicht werden und als c++ exception im programm wieder auftauchen. ich glaub' msvc kann sowas über diese TRY/EXCEPT macros.

-
In C++ eine NullPointerException bereitzustellen ist u.U. nicht trivial. Prinzipiell ist für das OS erstmal alles eine access violation. Zwischen dem speziellen Fall des 0-Pointers und einer "normalen" access violation zu unterscheiden, ist aber nicht ganz einfach. Zum Beispiel, wenn ich das zweite Elemente in einem struct mit einem 0-Pointer referenziere, könnte das die Adresse sein: 0x00000004
Klar, so ist es noch ganz einfach zu verstehen, dass die Ursache ein 0-Pointer ist, aber wo zieht man die Grenze? Wenn man nur die Adresse hat, ab welchem Wert ist es ein 0-Pointer und wann ist es was anderes? In Java ist die Frage leicht zu beantworten, weil es keine anderen Arten von access violations gibt (Arrayzugriff wird vorher vom Programm selber geprüft).
Um in C++ 0-Pointer Fehler eindeutig identifizieren zu können, müsste wahrscheinlich vor jeder Dereferenzierung ein expliziter Test auf 0 stattfinden. Das kostet Laufzeit und was ist jetzt der Gewinn dabei? Ich sehe ihn nicht.
-
ausnahme-freak schrieb:
bisher wird x/0 vom OS ausgewertet, das eine hässliche messagebox aufmacht (falls die exception nicht behandelt wird).
Also ich hab bei meinem Taschenrechner noch nie eine Messagebox gesehen.
-
Optimizer schrieb:
Zwischen dem speziellen Fall des 0-Pointers und einer "normalen" access violation zu unterscheiden, ist aber nicht ganz einfach.
z.b. windoofs spuckt bei exceptions ziemlich gute infos aus: http://msdn2.microsoft.com/en-us/library/aa363082(VS.85).aspx
LordJaxom schrieb:
Also ich hab bei meinem Taschenrechner noch nie eine Messagebox gesehen.
dann isser defekt. haste noch garantie?

-
Also ich bin eigentlich ganz froh, dass Speicher-Zugriffs-Fehler eher wie ein assert und nicht wie eine Ausnahme wirken. Genauso bei der Division durch 0, sowas will ich definitiv so früh raushaben wie möglich und bisher ließ sich bei mir mit Tests beides immer schön rausfiltern.
-
ausnahme-freak schrieb:
asc schrieb:
Bitte behaltet immer in Hinterkopf das C++ auch das Ziel hat effizient und schnell zu sein. Bei C++ wird nicht ohne grund einiges von Laufzeitentscheidungen in die Hand des Entwicklers gelegt. Wenn ich z.B. ausschließen kann das ich über die Indexe eines vectors zugreife, ist eine Prüfung eine unnötige Laufzeitbelastung.
nö, es muss ja nix ständig überprüft werden. eine aktion ist nur gefragt, wenn etwas passiert ist. bisher wird x/0 vom OS ausgewertet, das eine hässliche messagebox aufmacht (falls die exception nicht behandelt wird). sie könnte aber genauso gut an die c++ runtime library weitergereicht werden und als c++ exception im programm wieder auftauchen. ich glaub' msvc kann sowas über diese TRY/EXCEPT macros.

Wie soll das Funktionieren? Natürlich muss bei jedem Zugriff auf einen Zeiger geprüft werden, ob ein Nullpointer vorliegt. Selbiges gilt für das Überschreiten der Boundaries bei Arrays. Jeder Zugriff muss gecheckt werden.
Wie soll er denn sonst wissen, dass was passiert? Kristallkugel?
-
Tachyon schrieb:
Wie soll das Funktionieren? Natürlich muss bei jedem Zugriff auf einen Zeiger geprüft werden, ob ein Nullpointer vorliegt. Selbiges gilt für das Überschreiten der Boundaries bei Arrays. Jeder Zugriff muss gecheckt werden.
Wie soll er denn sonst wissen, dass was passiert? Kristallkugel?nö, das läuft hardwaregestützt ab. CPU, MMU etc. erkennen bus und alignment errors, division durch 0, access violations usw. und lösen einen interrupt aus. das betriebssystem sagt dem programm dann 'schau mal, was du da angestellt hast' und gibt ihm gelegenheit, darauf zu reagieren, indem dessen exception-handler (falls vorhanden) aufgerufen wird. im fall eines c++ programms könnte der exception handler in der c++ runtime lib sitzen, die dann daraus eine c++ exception machen könnte und das c++ programm könnte sie, wie gewohnt, mit einem 'catch' verarbeiten. es geschieht alles automatisch, ohne dass man aktiv irgendwas überprüfen muss.

-
os-freak schrieb:
Tachyon schrieb:
Wie soll das Funktionieren? Natürlich muss bei jedem Zugriff auf einen Zeiger geprüft werden, ob ein Nullpointer vorliegt. Selbiges gilt für das Überschreiten der Boundaries bei Arrays. Jeder Zugriff muss gecheckt werden.
Wie soll er denn sonst wissen, dass was passiert? Kristallkugel?nö, das läuft hardwaregestützt ab. CPU, MMU etc. erkennen bus und alignment errors, division durch 0, access violations usw. und lösen einen interrupt aus. das betriebssystem sagt dem programm dann 'schau mal, was du da angestellt hast' und gibt ihm gelegenheit, darauf zu reagieren, indem dessen exception-handler (falls vorhanden) aufgerufen wird. im fall eines c++ programms könnte der exception handler in der c++ runtime lib sitzen, die dann daraus eine c++ exception machen könnte und das c++ programm könnte sie, wie gewohnt, mit einem 'catch' verarbeiten. es geschieht alles automatisch, ohne dass man aktiv irgendwas überprüfen muss.

Jo, das stimmt. Das könnte mal tatsächlich so machen. Allerdings bedeuten Interrupts im Protected-Mode einen ordentlichen Schlag ins Gesicht des Betriebssystems...
-
hier mal ein beispiel, compiled mit msvc2005 unter win:
#include <stdio.h> #include <windows.h> int divide (int a, int b) { int res = 0; __try { res = a/b; } __except (1) // OS exception handler { throw "divison by zero"; } return res; } int main() { try { int x = divide (5, 0); } catch (char *what) // C++ exception handler { puts (what); } }