Ist "delete[]" zwingend erforderlich?



  • FPR schrieb:

    http://en.wikipedia.org/wiki/Dangling_pointer
    http://de.wikipedia.org/wiki/Hängender_Zeiger
    Was ich anfordere gebe ich auch ordentlich zurück.

    Naja, das ist so in alten Sprachen wie Pascal oder C/C++.

    Man stelle sich Folgendes vor:
    Oma bestellt einen Aufzug durch Druck auf den Knopf.
    Sie wartet ein Weilchen bis er da ist und steigt ein und fährt hin.
    Oma gibt nach Ausssteigen ihn zurück durch erneuten Druck auf den Knopf.

    Jo, alle von uns würden das als gestört empfinden. So genau sehen alle modernen Programmierer jedes delete als gestört.

    ~(Sorum argumentiert es sich leichter.)~



  • Siehe mein edit, volkard.

    Ausserdem hat Oma nach dem Aussteigen keinen Knopf wie "Erdgeschoß" von Aussen.
    Vergleich hinkt.



  • string function1() {
        string *Pointer;
        Pointer = new string[Index]; //Index wird aus einer anderen Funktion "geholt"
        string result = Pointer[1];
        delete[] Pointer;
        Pointer = 0;
        return result;
    }
    

    Wäre das dann so richtig?


  • Mod

    Navy schrieb:

    string function1() {
        string *Pointer;
        Pointer = new string[Index]; //Index wird aus einer anderen Funktion "geholt"
        string result = Pointer[1];
        delete[] Pointer;
        Pointer = 0;
        return result;
    }
    

    Wäre das dann so richtig?

    Zeile 4 kann eine Exception werfen.

    😕 Was soll das ganze Konstrukt überhaupt? Für eine theoretische Demonstration, wie das mit dem new und delete (wenn man es denn mal benutzt) richtig ginge, hat das denkbar viele Fehler (nämlich so ziemlich alle, wegen derer man new und delete nicht so ungekapselt benutzt). Und für einen echten, praktischen Code hat das total unnötige, ungekapselte new und delete.



  • Wie immer bin ich weit weniger höflich als SeppJ.
    Code ist Quatsch. Ganz offensichtlich hast du keine Ahnung was du tust.



  • FPR schrieb:

    http://en.wikipedia.org/wiki/Dangling_pointer
    http://de.wikipedia.org/wiki/Hängender_Zeiger

    Was ich anfordere gebe ich auch ordentlich zurück.

    EDIT:
    Man lässt pointer nicht einfach so hängen. Auch pointer haben Gefühle.

    Das klingt jetzt für mich so, als wenn Du da zwei Dinge verwechselst. Hängende Zeiger entstehen ja gerade deswegen, weil das, worauf sie zeigen, frei gegeben wird und man den (oder einen anderen, der dieselbe Adresse speichert) zu lange am Leben lässt.



  • krümelkacker schrieb:

    FPR schrieb:

    http://en.wikipedia.org/wiki/Dangling_pointer
    http://de.wikipedia.org/wiki/Hängender_Zeiger

    Was ich anfordere gebe ich auch ordentlich zurück.

    EDIT:
    Man lässt pointer nicht einfach so hängen. Auch pointer haben Gefühle.

    Das klingt jetzt für mich so, als wenn Du da zwei Dinge verwechselst. Hängende Zeiger entstehen ja gerade deswegen, weil das, worauf sie zeigen, frei gegeben wird und man den (oder einen anderen, der dieselbe Adresse speichert) zu lange am Leben lässt.

    Da hast du recht. Mea culpa.



  • Okay, dann versuche ich das jetzt einmal nachzuvollziehen.
    Der neu angeforderte Speicher muss wieder freigegeben werden, damit der RAM nicht irgendwann zu voll und zu langsam wird. Wenn dann der Pointer freigegeben wurde, hat dieser anscheinend aber noch die alten Arrays gespeichert/hat noch einen Inhalt. Wenn jetzt einer neuen Variable zufällig der vorherig verwendete, eigentlich freigegebene Pointer zugewiesen werden würde, hätte diese neue Variable dann den Inhalt des eigentlich freigegebenen alten Pointers. Wird bei der Variable jetzt abgefragt, ob diese bspw. leer ist, wird zurückgegeben, dass die Variable nicht leer ist, weil sie eben einem nicht gelöschten Pointer zugewiesen wurde. Also muss der Pointer "gelöscht" werden. Also wäre es doch richtig, nach dem "delete[] Pointer" "Pointer = NULL" zu schreiben. Oder ist das nicht so?

    SeppJ schrieb:

    Zeile 4 kann eine Exception werfen.

    😕 Was soll das ganze Konstrukt überhaupt? Für eine theoretische Demonstration, wie das mit dem new und delete (wenn man es denn mal benutzt) richtig ginge, hat das denkbar viele Fehler (nämlich so ziemlich alle, wegen derer man new und delete nicht so ungekapselt benutzt). Und für einen echten, praktischen Code hat das total unnötige, ungekapselte new und delete.

    Zeile 4 wirft eine Exception aus, wenn vorher nicht Pointer geleert wurde. So verstehe ich das 😃

    Aber wie soll ich denn sonst während der Laufzeit Speicher anfordern, wenn ich new und delete nicht benutzen darf? Was meint gekapselt eigentlich genau? Soll ich new und delete in eine eigene Funktion "auslagern"?



  • make_unique für unique_ptr (war glaube ich C++14), make_shared für shared_ptr (C++11).

    Oder

    std::unique_ptr<T> pointer(new T());
    


  • Navy schrieb:

    Okay, dann versuche ich das jetzt einmal nachzuvollziehen.
    Der neu angeforderte Speicher muss wieder freigegeben werden, damit der RAM nicht irgendwann zu voll und zu langsam wird. Wenn dann der Pointer freigegeben wurde, hat dieser anscheinend aber noch die alten Arrays gespeichert/hat noch einen Inhalt. Wenn jetzt einer neuen Variable zufällig der vorherig verwendete, eigentlich freigegebene Pointer zugewiesen werden würde, hätte diese neue Variable dann den Inhalt des eigentlich freigegebenen alten Pointers. Wird bei der Variable jetzt abgefragt, ob diese bspw. leer ist, wird zurückgegeben, dass die Variable nicht leer ist, weil sie eben einem nicht gelöschten Pointer zugewiesen wurde. Also muss der Pointer "gelöscht" werden. Also wäre es doch richtig, nach dem "delete[] Pointer" "Pointer = NULL" zu schreiben. Oder ist das nicht so?

    Nein, du hast da ein paar wirklich falsche Vorstellungen. Beispielsweise gibt es keine "leeren" Variablen, man kann daher sowas auch nicht abfragen. Ich denke, dein Hauptproblem ist, dass du das Freigeben mit dem Zeiger verbindest. Es ist aber gar nicht der Zeiger, der freigegeben werden muss, sondern das Objekt bzw. das Array, auf das der Zeiger zeigt, falls dieses mit new bzw. new[] erzeugt wurde.

    Wenn du ein Objekt freigibst, und den Zeiger, der nach wie vor auf dieselbe Adresse zeigt, wieder verwendest, können folgende Dinge passieren:

    - Es wurde inzwischen ein anderes Objekt an dieser Stelle erzeugt. Du liest bzw. veränderst also unkontrolliert Daten. Spezialfall: Es wurde ein Objekt desselben Typs an derselben Stelle erzeugt, dann kann dein Programm sogar mal scheinbar funktionieren.
    - An der Stelle liegt kein Objekt, aber dafür gewisse Daten, die die Speicherverwaltung intern benötigt. Wenn du da rumpfuschst, bekommst du irgendwann später einen Absturz.
    - Der freigegebene Speicher wurde an das Betriebssystem zurückgegeben, ein Zugriff auf eine nun ungültige Adresse führt direkt zum Absturz.



  • Ich benutze keine smart pointers, ich benutze keine exceptions.
    Das ist alles nur für Pussies. Real programmers don't need this.
    Du musst nur bewusst programmieren und den ganzen Kram abfangen.

    EDIT:
    link funktioniert erstaunlicherweise immer noch:
    http://www.pbm.com/~lindahl/real.programmers.html

    Auch noch nach dem zwanzigsten Mal Lesen muss ich laut loslachen.



  • @FPR: zeugt von einem eher einfachen Weltbild.
    Ich verstehe vollkommen, wenn die Leute keinen Bock auf diese new/malloc/delete/free -Scheiße haben. Wie leicht vertut man sich, übersieht, dass man einen Speicherbereich an einer Stelle freigeben will, oder dass man ihn schon freigegeben hat. Ich bin selbst eher C-Programmierer und stehe darauf, alles manuell zu machen. Aber so ein paar Sachen müssen echt nicht sein.

    Auf die Komplexitätsberge, die C++/Java mit sich bringen, stehe ich aber auch nicht. "Jesus Christus, da blickt ja kein Mensch durch", und wenn ich mir dann die Posts durchlese, in denen Leute Probleme beschreiben, die ich mit einem void* -Zeiger und eventuell noch mit einem enum , welches angibt, um welchen Typen es sich handelt, löse, wird mir ganz anders.
    Einige Features bezüglich der Codegenerierung sind ansonsten auch wirklich nett und verhindern Fehler.



  • dachschaden schrieb:

    @FPR: zeugt von einem eher einfachen Weltbild.

    Ich mag ein einfaches Weltbild in Bezug auf Programmierkonzepte haben, aber ich bin zu komplexen Gedankengängen fähig. Darum geht es mir.
    Das Ganze im Auge zu haben auch wenn es komplex wird. Ohne daß mich Mama am Händchen führt.

    EDIT:
    Ich kenne Leute, die widerspruchslos von Hand in 5000 Dateien die Umlaute ersetzten. Als sogenannter Programmierer. Ist ein netter Kerl, aber mir dürftest du mit so einem Job nicht kommen.



  • FPR schrieb:

    Ich benutze keine smart pointers, ich benutze keine exceptions.
    Das ist alles nur für Pussies. Real programmers don't need this.

    Mehr als dass diese Aussage totaler Bullshit ist gibt es dazu eigentlich nicht zu sagen.



  • hustbaer schrieb:

    FPR schrieb:

    Ich benutze keine smart pointers, ich benutze keine exceptions.
    Das ist alles nur für Pussies. Real programmers don't need this.

    Mehr als dass diese Aussage totaler Bullshit ist gibt es dazu eigentlich nicht zu sagen.

    Ich muss ja schließlich meinen Ruf aufrecht erhalten.

    ps:
    Ist trotzdem nur was für Pussies. :p

    Real Programmers write self-modifying code, especially if they can save 20 nanoseconds in the middle of a tight loop.

    Real Programmers don't need comments-- the code is obvious.



  • @FPR: setz dich mal mit Jürgen Wolf zusammen. Wenn ihr zusammen an einem Sachbuch arbeitet, hat dies das Potential, die Dämonen in der Programmiererhölle herbeizurufen. :p



  • dachschaden schrieb:

    @FPR: setz dich mal mit Jürgen Wolf zusammen. Wenn ihr zusammen an einem Sachbuch arbeitet, hat dies das Potential, die Dämonen in der Programmiererhölle herbeizurufen. :p

    Hehe.
    Leider kann der nicht strukturiert denken. Der Wolf ist eher ein Schaf.


Anmelden zum Antworten