Pointer und malloc frage



  • servus,

    ist es üblich pointer bzw. arrays immer zuerst mit NULL zu initialisieren also sowas:

    int* my_arr = NULL;
    

    Und ist das folgende eine übliche Art um zu testen ob malloc funktioniert hat?

    arr = (double *) malloc(sizeof(double));
    if (! arr) {
    	std::cout << "\n failed to malloc arr." << std::endl;
    	exit(1);
    }
    


  • oder wie sollte man wenn man z.B mit new alloziiert in C++ dann testen ob alles ok gegange ist...mittels try und catch dann abfangen?



  • Ja, new gibt ja nie NULL zurück, sondern schmeißt eine Exception, wenn kein Speicher mehr da ist. Im Regelfall ist aber immer genug Speicher da, außer du orderst einige Gigabyte 😃
    Grundsätzlich würde ich nicht damit rechnen, dass der Speicher leer wird, und wenn doch, dann musst du dein Prog wahrscheinlich beenden. Ich weiß nicht, was für eine Exception new dann schmeißt, aber die kannst du imho getrost in der main-Funktion auffangen, also alles in der main in einen try-Block schließen.
    Und ich glaube, man kann auch eine eigene Funktion angeben, die aufgerufen wird, wenn malloc nicht genug Speicher ranholen kann..



  • du imho getrost in der main-Funktion auffangen, also alles in der main in einen try-Block schließen.

    hmm wie sollte das gehen? Einfach wirklich in der main das komplette programm klammern?

    aber wie sieht der catch() - block dann aus ?



  • ...und macht man es nicht so, dass man jedesmal wenn man speicher alloziiert wirklich gezielt testet obs geklappt hat?



  • testo schrieb:

    du imho getrost in der main-Funktion auffangen, also alles in der main in einen try-Block schließen.

    hmm wie sollte das gehen? Einfach wirklich in der main das komplette programm klammern?

    main() ist das komplette Programm - alles andere wird (direkt oder indirekt) von dort aus aufgerufen.

    aber wie sieht der catch() - block dann aus ?

    Je nach Spezifität hast du die Wahl zwischen:

    catch(std::bad_alloc& e)  // das ist die Exception, die new bei Fehlern wirft
    {
      ...
    }
    catch(std::exception& e)  // das schließt alle in der STL auftretenden Exceptions ein
    {
      ...
    }
    catch(...)                // das fängt ALLES, was nicht bereits behandelt werden konnte
    {
      ...
    }
    


  • Danke - also macht man es nicht so dass bei jedem new getestet wird, sondern wirklich nur einmal in der main ein try-catch block mit std::bad_alloc ?



  • Nicht unbedingt in der main - normalerweise setzt man einen try-catch dorthin, wo man denkt, mit auftretenden Fehlern umgehen zu können.



  • testo schrieb:

    Danke - also macht man es nicht so dass bei jedem new getestet wird, sondern wirklich nur einmal in der main ein try-catch block mit std::bad_alloc ?

    könntest du machen. mit den exceptions hast du im gewissen sinne einen alternativen kontrollfluss in deinem programm.
    im unterschied zu 'new' werden bei 'malloc' keine exceptions geworfen. da musste dann weiterhin die 0 abfragen.
    🙂



  • Ich teste üblicherweise nicht, da bei new eher selten was schiefgeht. Lediglich wenn sehr große Mengen Speicher angefordert werden können halte ich einen Test für sinnvoll und natürlich wenn der aufgerufene Konstruktor eine Exception werfen kann. das ist aber ein anderes Problem.
    Es gibt eine Variante des Operator new der keine Exception wirft und statt dessen 0 zurückgibt.

    new(nothrow)
    


  • hmm.....ich weiß jetzt nicht wie es sauber wäre....wie macht man es denn üblicherweise?
    ich habe in meinem programm sehr viele new anweisungen und es könnte durchaus sein dass ich mehr als 1 GB alloziiere...des öfteren.

    Ich würde es gerne richtig machen bzw. so dass es sinnvoll & sauber ist...

    schwierig schwierig



  • Käme denn dein Programm theoretisch damit klar, wenn kein Speicher mehr zur Verfügung steht?
    Ich sehe 2 Möglichkeiten: 1. Der Speicher ist alle und du kannst dein Programm dichtmachen. Was willst du groß machen, wenn du z.B. noch nicht einmal eine Instanz einer Klasse anlegen kannst?
    2. Du stehst kurz davor, eine außergewöhnlich große Menge (z.B. halt mehr als 50 MB) an Speicher zu holen. Wenn das fehlschlägt, kannst du halt die folgende Berechnung, Speicherung oder was auch immer nicht durchführen. Oder du bastelst dir einen Ersatzalgo, der die Daten auf der Festplatte lagert und immer stückweise nachlädt.

    Für den ersteren Fall würde ich die Main-Funktion mit dem bad_alloc-try-Block umschließen, ne Meldung rausgeben und das Programm schließen. Im zweiten Fall kannst du das new oder die entsprechende Berechnungs-/Speicherungsfunktion mit einem solchen Block kapseln, bei Speichermangel eine Meldung ausgeben und das Programm ansonsten weiterlaufen lassen - oder halt auf die HDD-Lösung umsteigen.



  • Musst du denn wirklich die ganze Zeit sooo viel Daten im Speicher haben? Schau dich mal im Netz nach dem Proxy-pattern um. Dabei geht es darum, eine Klasse, die sehr viele Daten beinhaltet, so zu gestalten, dass sie Die Daten zwischenspeichern kann und nur bei Bedarf in den Arbeitspeicher laedt.



  • wie sieht es denn mit zeitkritischen anwendungen aus? Ich glaube das auslagern und einlagern in den Speicher kostet zu viel zeit....oder nicht? was macht man denn in dem fall?



  • Programme, die mit so großen Datenmengen hantieren müssen, sind nur selten zeitkritisch.



  • also ich kann mir vorstellen das bei numerischer simulation durchaus systeme betrachtet werden die z.B 10^10 einträge ...aber sicher weiß ich das jetzt nicht.

    Ich würde gerne eine bad_alloc exception auslösen- wie schaffe ich das?
    habe es banal mal so versucht:

    for(long i = 0; i < 2; i--)
    			int * arr = (int*) malloc(100000*sizeof(int));
    

    ging aber net 😕



  • Das ist auch nicht gerade GB-Bereich 🙂 Und, wie schon gesagt wurde, new wirft die Exception, malloc nicht...
    Und die heutigen Betriebssysteme können dir meistens auch ne Ecke mehr Speicher besorgen als das, was in den RAM passt. Das wird dann halt auch auf der Festplatte ausgelagert, dafür gibts in Windows die Auslagerungsdatei und unter Linux die Swap-Partition.

    edit: oh, ok, i--, wird wahrscheinlich doch GB-Bereich..



  • ich hirsch ...klar jetzt gehts....
    was wird denn in e gespeichert....ist das folgende soweit in Ordnung?

    try
    {
    ...
    }
    	catch(std::bad_alloc &e) 
    	{
    		std::cerr << e.what() << std::endl;
    		std::cerr << "\n\tPROGRAM ABORTED:\n\t\t  ERROR: Not enough memory.\n" << std::endl;
    		std::cerr << "\t===========================================\n" << std::endl;
    		abort();
    }
    


  • Was für Informationen bad_alloc wirklich mitbringt, ist vom Standard nicht spezifiziert. Das einzig sichere ist, daß e.what() eine (btw implementationsspezifische) Meldung gibt, die den eingetroffenen Fehler beschreibt.


Anmelden zum Antworten