Frage zu exceptions



  • Da ist kein Objekt... Kein Objekt -> Kein Dekonstruktoraufruf.
    Wenn ein Objekt da wäre würde es beim return 0 statement zerstört werden...



  • Es ist ein Objekt! Ja, i.d. Quellcode oben (den ich a.d. Kopf geschrieben habe) ist ein Fehler, das Objekt ist temporär, deshalb wird es sofort zerstört. Ich benutze den gcc-3.4.3. Wenn keine exc. geworfen wird, wird das Obj. am Ende zerstört. Wenn eine geworfen wird, wird der destruktor nicht aufgerufen.



  • Teste mal das hier:

    #include <iostream>
    
    class test
    {
    	public:
    		test(int a)
    		{
    			std::cout << "Konstruktor" << std::endl;
    		}
    		~test()
    		{
    			std::cout << "Dekonstruktor" << std::endl;
    		}	
    };
    
    void mach_dies()
    {
    	throw(1);
    }
    
    void mach_jenes()
    {
    	throw(1);
    }
    
    int main()
    {
        test(0);
    
    	try
        {
            mach_dies();
            mach_jenes();
        }
        catch(...)
        {
            std::cout << "Exception" << std::endl;
        }
    
    	std::cin.get();
    
        return 0;
    };
    

    Muss die Ausgabe Konstruktor - Dekonstruktor - Exception haben.



  • ness schrieb:

    Es ist ein Objekt! Ja, i.d. Quellcode oben (den ich a.d. Kopf geschrieben habe) ist ein Fehler, das Objekt ist temporär, deshalb wird es sofort zerstört. Ich benutze den gcc-3.4.3. Wenn keine exc. geworfen wird, wird das Obj. am Ende zerstört. Wenn eine geworfen wird, wird der destruktor nicht aufgerufen.

    entweder wird das objekt sofort zerstört, und zwar noch in derselben Zeile,also bevor du diesunddas() aufrufst, oder es handelt sich bei resource_allocator() um eine Funktion, die irgendwo ein Objekt anlegt (vermutlich mit new()), das dann nicht mehr gelöscht wird, weil du den entsprechenden Freigabebefehl (der dann delete aufrufen müsste) nicht aufrufst.

    Im ersten Fall müsste die Ressource eigentlich sofort wieder freigegeben werden, im letzteren wird sie evtl. übrig bleiben.

    Eine andere Möglichkeit ist, dass, während deine Exception irgendwelche Gültigkeitsbereiche verlässt, dort Destruktoren aufgerufen werden. Wenn in den Destruktoren wieder eine Exception geworfen wird (während die andere noch aktiv ist), dann wird sofort terminate aufgerufen und dein Programm verabschiedet sich ganz unentspannt ohne auch nur irgendein Objekt zu zerstören...



  • Aus diesem Grund sollte ein d'tor auch nie werfen..
    Aber wenn man ein throw() macht muesste theoretisch der copy c'tor aufgerufen werden, weil die geworfene Exception durch den copy c'tor(sollte man bei exceptions ausimplementieren und bei anderen Objekten im private Bereich deklarieren um seinen Aufruf zu verhindern) kopiert wird. Da das alte Objekt dann zerstoert wird, muesste der Destruktor einmal fuer das alte und einmal fuer die Kopie aufgerufen werden. Das geschieht beim vc++ 6.0 allerdings nicht was aeusserst seltsam ist.
    🤡 Wir gehen deshalb jetzt von nem internen Exception-Pool oder so aus *g*



  • Hallo,

    wow. sind ja wieder wilde Theorien hier im Umlauf.
    Um mal kurz auf den entscheidenen Punkt zu kommen:

    ob im Originalcode der Dtor aufgerufen wird oder nicht ist Implementations-abhängig. Der Originalcode besitzt *keinen* catch-Block und damit keinen Exceptionhandler. Der C++ Standard lässt es in diesem Fall offen, ob Stack-Unwinding stattfindet oder nicht. Dein Compiler führt in so einem Fall offensichtlich kein Stack-Unwinding durch.

    Ergo: Wann immer man Exceptions verwendet sollte zumindest jede Schnittstelle zur Außenwelt einen catch-All-Handler besitzen. Für ein Programm ist diese Schnittstelle die main-Funktion.

    Aber wenn man ein throw() macht muesste theoretisch der copy c'tor aufgerufen werden, weil die geworfene Exception durch den copy c'tor(sollte man bei exceptions ausimplementieren und bei anderen Objekten im private Bereich deklarieren um seinen Aufruf zu verhindern) kopiert wird

    Theoretisch. Praktisch gehört eine throw-Anweisung zu den Anweisungen in denen der Compiler den Copy-Ctor-Aufruf wegoptimieren darf.
    Sprich hier:
    [cpp]
    throw ExceptionClass();
    {/cpp]
    kann der Compiler das temporäre Objekt auch direkt im Speicher für das Exception-Objekt konstruieren und sich damit eine Kopie sparen.
    Voraussetzung: Der Copy-Ctor ist aufrufbar.



  • kann der Compiler das temporäre Objekt auch direkt im Speicher für das Exception-Objekt konstruieren und sich damit eine Kopie sparen.

    So rein interessehalber. Wie macht er das?



  • PunI$0R schrieb:

    kann der Compiler das temporäre Objekt auch direkt im Speicher für das Exception-Objekt konstruieren und sich damit eine Kopie sparen.

    So rein interessehalber. Wie macht er das?

    Nun, er hat doch alle Infos beisammen, er kann sehen das es ein Parameter für ein throw ist, er weiss das er das Objekt nur dafür braucht, also nimmt der den entsprechenden Speicher und löst dann dafür den Konstruktor für das Exception-Objekt aus. Da ist keine schwarze Magie nötig. 🤡 (Er muß es nicht tun, aber er darf.)



  • oehm wollte eigentlich nur sicher sein das er den c'tor nimmt..
    Das da keine schwarze Magie dahinter steckt war mir schon klar, soweit bin ich schon, das ich weiss das alles irgendwie funktioniert 😉



  • Danke für die klärung, HumeSikkins.


Anmelden zum Antworten