Frage wegen delete[] - funktion



  • Hallo liebe cpluspluser,

    ich habe hier ein problem mit der delete- funktion, und zwar habe ich 2 verschiedene methoden:

    Eine heisst FreeCalibrationData(), welche verwendete Daten wieder freigibt.

    diese methode führt das makro SAVE_DELETE() aus, welches überprüft, ob ein eintrag existiert: falls ja-> löscht es ihn, falls nein soll es nichts tun.

    code:

    #define SAVE_DELETE(x) if(x) { delete[] x; x = NULL; }

    wichtig: das makro wird auf dateien vom typ float* angewandt, zum beispiel:

    float* m_aXCalib;

    nun habe ich eine andere methode namens LoadCalibrationData(const char* i_sCalibrationFolder)

    Diese ruft gleich zu beginn die methode FreeCalibrationData() auf.

    im debug-modus habe ich festgestellt, dass das SAVE_DELETE- makro das programm zum absturz bringt, und zwar mit der fehlermeldung:

    "Unhandled exception at 0x610930ab (msvcr90d.dll) in FlyTriReg_x64_d.exe: 0xC0000005: Access violation reading location 0xffffffffffffffff."

    an der stelle:

    if (*pb++ != bCheck)
    { ..

    in der Datei dbgheap.c

    kurz beschrieben ist es also so:

    die methode loadCalibrationData ruft freeCalibrationData auf, bevor die Variablen überhaupt angelegt werden. die variablen sollen in freeCalibrationData gelöscht werden. eigentlich müssten die variablen jedoch den wert NULL besitzen, da sie nur deklariert, jedoch noch nicht initialisiert wurden. also müsste das makro SAVE_DELETE beim ersten durchlauf einfach nichts tun.

    weiss jemand wie man das problem beheben könnte bzw. hat eine theorie wo der fehler liegen könnte? danke schomal!


  • Mod

    Hast du diese Funktionen selbst geschrieben? Gibt es die Möglichkeit, ihre Benutzung zu umgehen?

    Falls ja: Alles wegwerfen, vector benutzen.
    Falls nein: Beten. Deine Seele ist verdammt.

    Hier haben wir alle typischen Alarmsignale für schlechten Code: Manuelle Speicherverwaltung. Noch dazu für Arrays. Makros. Noch dazu SAFE_DELETE Makros. Nullen von Zeigern. Eigener Nachbau von Klassenfunktionalität.

    Esoterik trifft schlechte Praktiken. Hier geht alles schief, was nur schief gehen kann, da gibt es nichts zu retten.



  • Du darfst keinen Pointer zu einem einzigen Typen mit delete[] freigeben.



  • Ich muss dazu sagen, ich habe das Programm nicht selber geschrieben, sondern soll mich einarbeiten und einige Funktionalitäten einbauen. Allerdings kriegen wir den Debugger nicht zum laufen deshalb wird es schwer sonst weiterzumachen.
    Das Programm ist Teil einer Doktorarbeit in Informatik, von daher denke ich schon dass der Kerl wusste was er tut (hoffentlich!)



  • SeppJ schrieb:

    Beten. Deine Seele ist verdammt.

    Dieses elende (noch dazu falsch geschriebene) Makro ist die Wurzel alles Bösen. Bitte sofort verbrennen.

    #define SAVE_DELETE(x)	if(x) { delete[] x; x = NULL; }
    

  • Mod

    beinando123 schrieb:

    Das Programm ist Teil einer Doktorarbeit in Informatik, von daher denke ich schon dass der Kerl wusste was er tut (hoffentlich!)

    Nein. Es ist Esoterik. Nicht "nur" Esoterik, die dich unnötig kostet (Magnete um das Haus vergraben, Feng Shui und ähnliches), sondern Esoterik, die dir aktiv schadet (Alternativmedizin bei richtigen Krankheiten, Quecksilbertrinken, Aderlass und ähnliches).

    Was hier zu tun ist, ist eine schwere Frage. Der gezeigte Code selbst ist der Fehler. Ein riesengroßer Fehler. Wenn du bei dem Code bleibst, wirst du bloß unglücklich damit. Dies ist abzuwägen gegenüber dem äußerem Zwang, zu tun, was deine Vorgesetzten dir sagen.
    Da es eine Doktorarbeit ist, würde ich tendenziell eher empfehlen, dass du den Code auf die Scheiterhaufen wirft, wo er hingehört. Du bist jetzt schließlich selber verantwortlich. Mit diesem Code wirst du die nächsten drei Jahre bloß rumfrickeln. Schlimmer noch, vielleicht musst du nach 18 Monaten alles wegwerfen, weil du erkennst, dass das alles Mist ist. Andererseits hast du jetzt noch die Zeit, modernes C++ zu lernen und dann von Grund auf alles richtig zu machen.

    P.S.: Es ist natürlich noch die Frage, ob du diese Entscheidung aufgrund von irgendwelchen Tipps aus dem Internet treffen möchtest. Da kann ich auch nicht viel zu sagen. Da musst du abwägen, wem du mehr Kompetenz zutraust. Auf der einen Seite jemand, den du persönlich kennst und einschätzen kannst. Dessen Code nachgewiesen nicht funktioniert. Auf der anderen Seite anonyme Internetaccounts. Aber Accounts die sehr aktiv sind in einem Forum, in dem es den ganzen Tag bloß ums Programmieren geht.



  • also es ist nicht meine doktorarbeit, die ich auf diesem code aufbaue. der code selber war die doktorarbeit, die ist auch schon durch und abgegeben. ich muss nurnoch 1-2 zusätzliche funktionen einbauen im rahmen einer masterarbeit - das ganze programm sind geschätzt <100000 zeilen, also von neu aufziehen wird da eher schwierig. die einzige alternative zu dem makro, welches ich gefunden habe, ist:

    template<typename T> void safe_delete(T*& a) {
    delete a;
    a = NULL;
    }

    damit ging es jedenfalls auch nicht .. es ist einfach schwierig was zu ändern, weil ich keine ahnung habe was für auswirkungen meine änderungen in irgendwelchen von den X anderen klassen/funktionen haben können .


  • Mod

    Wie schon gesagt, gibt es da nicht viel zu retten. Tut mir Leid für die unbefriedigende Antwort, aber ist eben einfach so. Der Code ist unwartbar und ich bin ehrlich gesagt schwer überrascht, dass da überhaupt etwas Funktionierendes mit gemacht wurde. Mehr noch, wenn das Programm wirklich 100,000 Zeilen hat. (Ohne es zu kennen wette ich, dass davon 80,000 problemlos entfernt werden könnten.)

    Der Tipp kann nur sein, diese Funktionen nicht zu benutzen und möglichst drumherum zu programmieren. Du brauchst in C++ (fast) nirgendwo new und delete. Und nirgendwo new[] und delete[]! Nimm für deinen eigenen Code einfach vector (statt new[] und delete[]), automatische Objekte (für falsch gesetzt new und delete) oder unique_ptr (für zwar richtige, aber schlecht benutzte new und delete).
    Wenn der restliche Code nicht zu schlimm ist (und beispielsweise nicht anfängt new und delete oder gar malloc und free im Interface zu benutzen), dann bieten die obigen Mittel alles was man braucht, um auch das hässlichste Interface zu bedienen. Du benutzt dann nur die Funktionen, die wirklich etwas tun. Die ganze Speicherverwaltung machst du selber. Was mit den oben genannten Mittel übrigens auf ein entspanntes Nichtstun hinausläuft.



  • Wurde der Code irgendwo hochgeladen oder woher weißt du, dass er unwartbar ist?



  • beinando123 schrieb:

    die methode loadCalibrationData ruft freeCalibrationData auf, bevor die Variablen überhaupt angelegt werden. die variablen sollen in freeCalibrationData gelöscht werden. eigentlich müssten die variablen jedoch den wert NULL besitzen, da sie nur deklariert, jedoch noch nicht initialisiert wurden. also müsste das makro SAVE_DELETE beim ersten durchlauf einfach nichts tun.

    Das ist nicht so. Ganz im Gegenteil werden die Zeiger mit großer Sicherheit einen Wert != NULL haben.


  • Mod

    Bashar schrieb:

    Wurde der Code irgendwo hochgeladen oder woher weißt du, dass er unwartbar ist?

    100,000 Zeilen und alle Ausschnitte die wir sehen sind Musterbeispiele für wie man es nicht macht.



  • beinando123 schrieb:

    #define SAVE_DELETE(x)	if(x) { delete[] x; x = NULL; }
    

    wichtig: das makro wird auf dateien**[?]** vom typ float* angewandt, zum beispiel:

    Manchmal bin ich dankbar dafür, dass es Java gibt. Leute, die keine Zeit haben, richtig C++ zu lernen, sind bei Java besser aufgehoben.



  • +1



  • Vor einiger Zeit sprach ich mit einem Gamecoder. Nunja, eventuell hätte ich Lust gehabt, am Projekt mitzuwirken. Um mich zu testen, frage er mich, wie man safe-delete RICHTIG implementiert.
    Ich wußte es natürlich: Als Template (unter anderem mit Referenz auf Zeiger) und nicht als Makro. Aber irgendwie dachte ich mir, daß die Mitarbeit dort dann doch zu mühsam wäre.



  • SeppJ schrieb:

    Noch dazu SAFE_DELETE Makros.

    SAVE_DELETE. Ich weiß, wurde schon gesagt. Find ich trotzdem lustig 🙂


  • Mod

    Mechanics schrieb:

    SeppJ schrieb:

    Noch dazu SAFE_DELETE Makros.

    SAVE_DELETE. Ich weiß, wurde schon gesagt. Find ich trotzdem lustig 🙂

    Autsch. Jetzt fällt mir das erst auf. Dabei fragte ich mich die ganze Zeit, was Nexus auf der ersten Seite meinte. 💡

    Mit der Schreibweise fällt das schon fast unter Satire. Vielleicht legen sie den Neuen rein? Die Informatikerversion von Feilenfett und Getriebesand?



  • SeppJ schrieb:

    Getriebesand?

    Wirst lachen, es ist eine nicht unübliche Methode, Sand in Zauberwürfel zu schütten und sie dann 20- 30-mal zu lösen, bevor man den Sand wieder komplett wegmacht und den Würfel schmiert. Damit alle Herstellungsungenauigkeiten, die störende Hubbel waren, dann gewesen sind.

    Als es noch keine elektronischen Waagen gab, waren Balkenwaagen und Abarten wie Dezimalwaagen viel viel genauer als Federwaagen und deshalb üblich mitsamt Gewichten, weshalb "Hol mal die Gewichte für die Wasserwaage" klappte.
    Und wer kein Gefühl für "Schwung" hat, den läßt man auch mal eine "Kolbenrückholfeder" holen.



  • volkard schrieb:

    Vor einiger Zeit sprach ich mit einem Gamecoder. Nunja, eventuell hätte ich Lust gehabt, am Projekt mitzuwirken. Um mich zu testen, frage er mich, wie man safe-delete RICHTIG implementiert.
    Ich wußte es natürlich: Gar nicht, weil man es nie braucht.

    FTFY

    Oder, wo zum Teufel braucht das ein richtiger C++-Programmierer mit C++03? 🙂

    Btw: Ist es nicht schon immer so gewesen, dass delete ( [] ) Bei Null-Zeigern SOWIESO nichts macht?



  • was ist denn die alternative zu dem makro? soll ichs mit einer inline- funktion versuchen ?



  • beinando123 schrieb:

    was ist denn die alternative zu dem makro? soll ichs mit einer inline- funktion versuchen ?

    Gar nichts. Du brauchst das nicht. Schreib delete[] und fertig - oder nimm gleich std::vector, wie hier schon gesagt wurde.


Log in to reply