Exceptions und operator delete()



  • Folgender Code:

    #include <iostream>
    #include <exception>
    #include <cstddef>
    using namespace std;
    
    class AllocWithException {
    public:
    	AllocWithException()
    	{
    		throw exception();
    	}
    
    	static void* operator new(size_t size)
    	{
    		cout << "operator new()" << endl;
    		return ::operator new(size);
    	}
    
    	static void operator delete(void* ptr)
    	{
    		cout << "operator delete()" << endl;
    		::operator delete(ptr);
    	}
    };
    
    int main()
    {
    	AllocWithException* a = new AllocWithException;
    
    	delete a;
    }
    

    Konsole:
    operator new()

    Die Ausgabe sollte aber lauten:

    Konsole:
    operator new()
    operator delete()

    Warum das eigentlich so sein sollte, kann man in C++ Coding Standards,
    Guideline 45 nachlesen. Da gabs auch nen Verweis auf den Standard:

    §5.3.4(17) - If any part of the object initialization described above
    terminates by throwing an exception and a suitable deallocation
    function can be found, the deallocation function is called to free
    the memory in which the object was being constructed, after which
    the exception continues to propagate in the context of the new-expression.
    If no unambiguous matching deallocation function can be found,
    propagating the exception does not cause the object's memory to be freed.
    (leicht veränderte Fassung)

    Geht also auch hier ganz klar raus, das die 2. Ausgabe erscheinen müsste.
    Warum wird aber die 1. Version ausgegeben ? Hab ich was falsch gemacht ?

    (Kompiliert mit gcc 3.3.1, klappt aber anscheinend auch mit 3.4 nicht)

    Tankian



  • Hmm, würd mich auch interessieren. Du hast recht, ich würde auch beide Textausgaben erwarten.



  • <... war misst ...>



  • Hallo,
    zumindest wenn du die Exception fängst, also das Programm wie folgt änderst (und damit ein terminate verhinderst):

    try {AllocWithException* a = new AllocWithException; }
    catch(...) {}
    

    wird auch wie gewünscht "operator delete()" ausgegeben.



  • Hallo,
    zumindest wenn du die Exception fängst, also das Programm wie folgt änderst (und damit ein terminate verhinderst):

    try {AllocWithException* a = new AllocWithException; }
    catch(...) {}
    

    Ich suchte eigentlich nicht nach Alternativen, da ich einfach nur probieren,
    wollte ob es wirklich stimmt was ich gelesen hatte, anscheinend bleibt es wohl
    beim "müsste klappen" ..

    Aber trotzdem danke 🙂

    Tankian



  • Interessant wäre mal, den terminate_handler zu ändern. (Weiß jetzt nicht auswendig, wie das geht, sonst hätt ich's gleich probiert)



  • Interessant wäre mal, den terminate_handler zu ändern.

    Dann würd dir vielleicht die Funktion set_terminate helfen.



  • So geht's:

    #include <iostream>
    #include <exception>
    #include <cstddef>
    using namespace std;
    
    class AllocWithException {
    public:
        AllocWithException()
        {
            throw exception();
        }
    
        void* operator new(size_t size)
        {
            cout << "operator new()" << endl;
            return ::operator new(size);
        }
    
        void operator delete(void* ptr)
        {
            cout << "operator delete()" << endl;
            ::operator delete(ptr);
        }
    };
    
    int main()
    {
        try
        {
            AllocWithException* a = new AllocWithException;
            delete a;            //Kann zu Testzwecken auskommentiert werden, ändert an der Ausgabe des Programmes nichts (erzeugt aber in richtigen Programmen dann ein Speicherleck)
        }
        catch(...)
        {
            cout << "caught an exception" << endl;
        }
    }
    

    Ausgabe:

    operator new()
    operator delete()
    caught an exception
    


  • Tankian schrieb:

    Hallo,
    zumindest wenn du die Exception fängst, also das Programm wie folgt änderst (und damit ein terminate verhinderst):

    try {AllocWithException* a = new AllocWithException; }
    catch(...) {}
    

    Ich suchte eigentlich nicht nach Alternativen, da ich einfach nur probieren,
    wollte ob es wirklich stimmt was ich gelesen hatte, anscheinend bleibt es wohl
    beim "müsste klappen" ..

    das ist ja keine Alternative, sondern wie Hume schon gesagt hat, wird einfach terminate aufgerufen, wenn die Ausnahme geworfen wird diese aber nicht gefangen wird. Steht auch im Standard so.



  • Steven schrieb:

    cout << "catched an exception" << endl;
    

    caught 🤡



  • Hab's verbessert. Peinlich, peinlich... 🙄 😞


Anmelden zum Antworten