Wie Speicherfehler behandeln



  • Hi,

    wenn man per new Speicher anfordert und dieses nicht gelingt wird ja eine bad_alloc Exception geworfen. Nun ist meine Frage: Intern werden ja auch dauernd
    neue Objecte erstellt und denke mal auch mit new erstellt.
    z.B.

    std::string foo( void )
    {
        return( "1234" );
    }
    

    Da müssen ja mindestens 5 Bytes intern angefordert werden.
    Was passiert wenn dies nicht möglich ist?
    Wird dann auch eine bad alloc Exception geworfen?

    mfg



  • Globaler exception handler installieren und filter dazu schreiben.
    http://msdn2.microsoft.com/en-us/library/5z4bw5h5.aspx

    Übrigens wird in deinem Bsp. (bei nur 5 character) bei den meisten Impl. von std::string kein Speicher auf dem Heap (mit new) alloziert.

    Gruss Simon



  • simon.gysi schrieb:

    Globaler exception handler installieren und filter dazu schreiben.
    http://msdn2.microsoft.com/en-us/library/5z4bw5h5.aspx

    Sieht irgendwie nicht sehr plattformunabhängig aus 😉

    @Topic:
    Alles, was new oder new[] benutzt, wirft bad_alloc. Dynamische Datenstrukturen in der Standardbibliothek benutzen Allokatoren, und der (einzige) Allokator der Standardbibliothek nutzt seinerseits new oder new[]. Damit wirft erstmal alles, was aus dem Standard kommt und Speicher anfordert, im Fehlerfall bad_alloc.


  • Mod

    LordJaxom schrieb:

    der (einzige) Allokator der Standardbibliothek nutzt seinerseits new oder new[]

    nicht ganz. Der Defaultallokator benutzt ::operator new(size_t) bzw. ::operator delete(void*) - also die globale nicht-array nicht-placement Allokations-/Deallokationsfunktionen. Deshalb wird für diesen Allokator auch nicht noch einmal extra das Verhalten im Fehlerfall festgelegt, dieses ist bereits durch die Spezifikation jener Funktionen bestimmt (==new ruft im Fehlerfall den new_handler auf bzw. wirft bad_alloc).



  • In deinem konkreten Beispiel wird gar kein Speicher dynamisch alloziert. Der String landet im Binary einfach im Textsegment. In Java sieht das natürlich anders aus 🙂


  • Mod

    Hindman schrieb:

    In deinem konkreten Beispiel wird gar kein Speicher dynamisch alloziert. Der String landet im Binary einfach im Textsegment. In Java sieht das natürlich anders aus 🙂

    Es wird ein std:string konstruiert, und dabei muss das Literal irgendwohin kopiert werden.



  • camper schrieb:

    Es wird ein std:string konstruiert, und dabei muss das Literal irgendwohin kopiert werden.

    In manchen Implementierungen von std::string stehen ein paar Bytes zur Verfügung um dort kurze Strings einfach ablegen zu müssen. Kann man aber natürlich nicht von ausgehen.



  • Ein vernüftiges Vorgehen ist also mit set_new_handler einen new- handler installieren und dort die speicherknappheit gehandeln (wie auch immer).

    Korrekt?



  • Vielen Dank,

    ich werde es jetzt folgendermaßen machen.
    Für jede Klasse den new Operator überladen und die set_new_handler Funktion benutzen.

    mfg



  • Eine Frage ist mir noch eingefallen.
    Gibt es eine möglichkeit den operator new für die standart Typen wie int oder float zu überladen?



  • Was spricht gegen ein catch bad_alloc in main, wenn man davon absieht, dass bad_allocs in der Konstruktion globaler Objekte nicht gefangen würden?



  • plongor schrieb:

    Eine Frage ist mir noch eingefallen.
    Gibt es eine möglichkeit den operator new für die stan**** Typen wie int oder float zu überladen?

    Du kannst den globalen Operator new überladen, also für ALLE Typen. Für einzelne ausgewählte build ins soweit ich weiß allerdings nicht.



  • So, jetzt funktioniert alles wie ich es wollte.
    Eine allerletzte Frage habe ich aber noch.
    Woher weiß ich wieviel Speicher mein Programm auch ohne new Anfragen benutzt?
    Das muss der Compiler bzw. das Betriebsystem ja vorher wissen.
    wenn ich zum Beispiel

    void foo( void )
    {
        char test[ 100 ];
    }
    
    int main( int argc, char** argv )
    {
        foo();
    }
    

    mache, muss das OS ja wissen, ob genügend Speicher vorhanden ist um die Funktion foo auszuführen. Wo werden die 100 Bytes dann überhaupt hingespeichert?
    Müssten die nicht eg intern dann auch wieder mit new angefordert werden?



  • Wo werden die 100 Bytes dann überhaupt hingespeichert?

    Auf dem Stack.



  • LordJaxom schrieb:

    Was spricht gegen ein catch bad_alloc in main, wenn man davon absieht, dass bad_allocs in der Konstruktion globaler Objekte nicht gefangen würden?

    Das müsste dann bei jedem Thread gemacht werden.
    Mit dem new handler wäre das "global" geregelt.

    Mein Verständnis für die std::bad_alloc oder den new handler sind so, dass wenns schief geht, ist es im allgemeinen nicht mehr so super und ich dann noch z.B. ein Log Eintrag erzeugen kann, bevor das Programm terminiert wird.

    Simon


Anmelden zum Antworten