Throw in unexpected()

ibafluss

Erfahrenes Mitglied
Hey Leute!
Im folgenden Programm wird im main() im zweiten try bei der Erstellung von Noisy n4 eine Exception vom Typ char geworfen, die jedoch in der Funktionsdefinition (Konstruktor von Noisy) nicht erwähnt wird. Wenn dann unexpected_rethrow() aufgerufen wird sollte die Funktion eigentlich die Exception weiterwerfen. Es kommt jedoch die Programmausgabe, dass eine Exception nicht aufgefangen wurde (The programm terminated in an unusual way....). Ich habe auch schon die ganze main() in einen try-Block gehüllt, das Ergebnis blieb jedoch das selbe. Eigentlich sollte die Exception im main() nach dem 2. try aufgefangen werden.

C++:
#include <fstream>   
#include <exception>
#include <cstring>
#include <cstdlib>

using namespace std;

ofstream out ("test.txt");

class Noisy
{
    static int i;
    int objnum;
    enum {sz = 40};
    char name[sz];

    public:
            Noisy (const char *nm = "array elem") throw (int)
            {
                objnum = i++;
                memset (name, 0, sz);
                strncpy (name, nm, sz-1);
                out << "Constructing Noisy " << objnum << "name [" << name << "]" << endl;

                if (objnum == 5)
                {
                    throw int (5);
                }

                if (*nm == 'z')
                {
                    throw char ('z');
                }
            }

            ~Noisy()
            {
                out << "destructing Noisy " << objnum << " name [" << name << "]" << endl;
            }

            void* operator new[] (size_t sz)
            {
                out << "Noisy::new[]" << endl;

                return ::new char[sz];
            }

            void operator delete[] (void *p)
            {
                out << "Noisy::delete[]" << endl;
                ::delete []p;
            }
};

int Noisy::i = 0;

void unexpected_rethrow()
{
    out << "inside unexpected rethrow()" << endl;

    throw;
}

int main()
{
    set_unexpected (unexpected_rethrow);

    try
    {
        Noisy n1 ("before array");
        Noisy *array = new Noisy[7];
        Noisy n2 ("after array");
    }
    catch (int i)
    {
        out << "caught " << i << endl;
    }

    out << "testing unexpected: " << endl;

    try
    {
        Noisy n3 ("before unexpected");
        Noisy n4 ("z");
        Noisy n5 ("after unexpected");
    }
    catch (char c)
    {
        out << "caught " << c << endl;
    }
}

Lg
 
Hi.

Wenn du throw im unexpected Exception Handler aufrufst, wird terminate aufgerufen (falls bad_exception nicht in der throw Klausel der Funktion steht.

Du kannst also eine unerwartete Ausnahme nicht direkt weiterwerfen und auffangen. Der Compiler dürfte sogar den catch (char) Block eleminieren, da laut throw Klausel keine "char" Exception geworfen werden kann.

Gruß
 
Das ist ein Beispiel aus meinem C++ Buch. Im Buch steht, dass die Exception weitergeworfen wird und im Buch steht statt dem throw; nur ein exit(0); in unexpected_rethrow(). Ich dachte, dass das ein Schreibfehler ist, weil exit(0) beendet ja nur das Programm, deshalb habe ich versucht, das Problem mit throw zu lösen. Gibt es dafür also keine Möglichkeit?

Lg
 
Das ist ein Beispiel aus meinem C++ Buch.
Evtl. hast du da etwas nicht richtig verstanden oder es steht nicht genau drin?
Im Buch steht, dass die Exception weitergeworfen wird
Man kann eine Exception werfen, aber nur eine die "erwartet" ist.

Man kann auch eine unerwartete Exception werfen, wie z.B. dieselbe Exception aufgrund derer der Handler aufgerufen wurde, aber nur falls std::bad_exception eine "erwartete" Exception laut throw Klausel ist.
und im Buch steht statt dem throw; nur ein exit(0); in unexpected_rethrow(). Ich dachte, dass das ein Schreibfehler ist, weil exit(0) beendet ja nur das Programm, deshalb habe ich versucht, das Problem mit throw zu lösen.
Problem? Wieso Problem?
Gibt es dafür also keine Möglichkeit?
Wozu? Das wäre grober Unfug. Warum sollte man definieren, das nur bestimmte Ausnahmen geworfen werden können und dann doch eine andere werfen um diese durch Umwege als "normale" Exception durchzuschleusen und zu behandeln?

Gruß
 
Von diesem Buch gibt es anscheinend viele Versionen (heißen zwar alle 2nd Edition, der Inhalt ist jedoch verschieden). Das Beispiel was in meinem Buch steht, ist sonst komischerweise in keinem. Kann es sein, dass ich eine fehlerhafte Version habe? Ich habe die Seite mal als Anhang hinzugefügt. Da es mit HTML nicht funktioniert, habe ich sie in ein *.txt Datei verpackt. Ich hoffe, sie ist halbwegs lesbar.

Lg
 

Anhänge

Offenbar Thinking in C++, 2nd edition von Bruce Eckel.
gibt es anscheinend viele Versionen (heißen zwar alle 2nd Edition, der Inhalt ist jedoch verschieden). Das Beispiel was in meinem Buch steht, ist sonst komischerweise in keinem. Kann es sein, dass ich eine fehlerhafte Version habe?
Das könnte durchaus sein. Papier ist geduldig und es gibt einige schlechte C++ Bücher.
Ich habe die Seite mal als Anhang hinzugefügt. Da es mit HTML nicht funktioniert, habe ich sie in ein *.txt Datei verpackt. Ich hoffe, sie ist halbwegs lesbar.
Also das
Thus, the effect of unexpected_rethrow(
) is to take any unexpected exception and make it expected; used this
way it provides a filter to allow you to track the appearance of
unexpected exceptions and pass them through.
ist ziemlicher Nonsens. Zumal die gezeigte Version die Ausnahme gar nicht weiterwirft, sondern wie du schon sagtest einfach exit(0) aufruft. Hier ist offenbar eine verbesserte Version: http://www.codeguru.com/cpp/tic/tic0260.shtml mit der gleichen Behauptung.

\edit: Übrigens, laut C++ Standard (http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2011/n3242.pdf)
The std::unexpected() function shall not return, but it can throw (or re-throw) an exception. If it
throws a new exception which is allowed by the exception specification which previously was violated, then
the search for another handler will continue at the call of the function whose exception specification was
violated. If it throws or rethrows an exception that the dynamic-exception-specification does not allow
then the following happens: If the dynamic-exception-specification does not include the class std::bad_-
exception (18.8.2) then the function std::terminate() is called, otherwise the thrown exception is replaced
by an implementation-defined object of the type std::bad_exception and the search for another handler
will continue at the call of the function whose dynamic-exception-specification was violated.
Was Bruce Eckel da also schreibt ist tatsächlich einfach Unsinn und es wäre auch ziemlich sinnfrei.

Gruß
 
Zuletzt bearbeitet:
Zurück