Probleme mit malloc / free (DAMAGE: after Normal block (#142) at 0x00B65A20.)



  • Dein Array ist aber nicht groß genug für i==sg.



  • Tachyon schrieb:

    Dein Array ist aber nicht groß genug für i==sg.

    Versteh ich nicht, denn i <= sg, beinhaltet auch den Fall i==sg.

    Im übrigen fliegt der Code schon viel eher (schrieb ich auch) und zwar hier:

    // Speicher bereit stellen
    if(arr == NULL) {
       arr = (char**)malloc(sg * sizeof(char*));		
       if (arr == NULL) {
          printf("Konnte keinen Speicher reservieren.\n");
          return sg;
       }
    }
    

    Und das hat nichts mit einer Schleife zu tun.



  • lunatic82 schrieb:

    if(arr == NULL) {
       arr = (char**)malloc(sg * sizeof(char*));		
       if (arr == NULL) {
          printf("Konnte keinen Speicher reservieren.\n");
          return sg;
       }
    }
    

    Und das hat nichts mit einer Schleife zu tun.

    Dann machst Du schon verher was kaputt. Das oben stehende sollte gehen.

    Nochmal:
    Hier...

    arr = (char**)malloc(sg * sizeof(char*));
    

    ...reserviertst Du für sg Elemente Speicher. Der Index geht von 0..sg-1 .

    Hier hingegen...

    for(i=0; i <= sg; i++) { ...
    

    ...greist Du auf 0..sg zu. Ein Element mit dem Index sg existiert aber nicht.



  • lunatic82 schrieb:

    Tachyon schrieb:

    Dein Array ist aber nicht groß genug für i==sg.

    Versteh ich nicht, denn i <= sg, beinhaltet auch den Fall i==sg.

    Eben drum. Von 0..sg sinds insgesamt sg+1 Schritte, und du reservierst nur Speicher für sg Pointer. Typischer Zaunlattenfehler 😉

    Im übrigen fliegt der Code schon viel eher (schrieb ich auch) und zwar hier:

    // Speicher bereit stellen
    if(arr == NULL) {
       arr = (char**)malloc(sg * sizeof(char*));		
       if (arr == NULL) {
          printf("Konnte keinen Speicher reservieren.\n");
          return sg;
       }
    }
    

    Und das hat nichts mit einer Schleife zu tun.

    Da gibts zwei mögliche Gründe warums fliegt:

    1. printf() - Unwahrscheinlich, aber ersetz es mal testweise mit cout bzw. cerr, schließlich machst du eh C++ bzw. gibst es mit deiner Klasse zumindest vor.
    2. malloc() - auch unwahrscheinlich. Du könntest es allerdings zum Testen mal nurch ein new char*[sg+1] ersetzen.

    Bist du tatsächlich mit dem Debugger durchgesteppt und hast rausgefunden dass es dort fliegt? Eventuell geht auch die Funktion die du im assert() aufrufst in die Hose, wäre zumindest ein idealer Kandidat dafür (heißt CheckMemory und du bekommst Memory check error...)



  • @Tachyon:
    Ja stimmt, jetzt wird mir das auch klar. Manchmal ist man echt blind.

    @pumuckl:
    Aber selbst, wenn ich die Anmerkung von Tachyon berücksichtige, bricht er mir schon beim ersten malloc oder new, wenn ich die assert-Bedingung drin habe. Wenn ich die entferne, dann geht er bis zum zweiten malloc oder new und dann bricht er dort mit einer Exception ab.

    1. printf ist es definitiv nicht
    2. assert meldet schon korrekt, dass der Heap beschädigt ist, deswegen funktioniert das zweite malloc nicht. Wenn dort i=i ist, dann fliegt er eben an dieser Stelle.

    Ich steppe in der Tat mit dem Debugger durch den Quelltext und schaue mir an, was dort passiert. Und es ist mir unerklärlich. split bzw. flush sind auch die einzigen Funktionen, die dynamisch in dem Code Speicher reservieren.

    Gibt es noch andere konstruktive Ideen?



  • lunatic82 schrieb:

    Gibt es noch andere konstruktive Ideen?

    Gibt es einen Grund dafür, warum du dich mit diesen altertümlichen und fehleranfälligen C-Konstrukten abquälst, statt die Sache sauber mit C++-Strings zu implementieren?



  • Registrierter Troll schrieb:

    Gibt es einen Grund dafür, warum du dich mit diesen altertümlichen und fehleranfälligen C-Konstrukten abquälst, statt die Sache sauber mit C++-Strings zu implementieren?

    Weil ich zum sauberen Verarbeiten der Informationen eh wieder alles in einen char** umwandeln muss und aus Gründen der Portabilität käme eh nur std::string und nicht CString in Frage.

    Und std::string isst genau so ein Krampf.



  • lunatic82 schrieb:

    Weil ich zum sauberen Verarbeiten der Informationen eh wieder alles in einen char** umwandeln muss und aus Gründen der Portabilität käme eh nur std::string und nicht CString in Frage.

    Selbst wenn du nachträglich alles in char-Arrays packen müsstest, was ich ehrlich gesagt für unwahrscheinlich halte, wäre die Suche und das letztendliche Zusammenbauen des Strings eine Sache von ein paar wenigen Zeilen - ohne Buffer overflows und sonstigen Newbie-Krebs.

    Wer sagte eigentlich irgendwas von CString?

    Und std::string isst genau so ein Krampf.

    Du irrst dich gewaltig. Alle deine Probleme wären wie weggezaubert, weil du dich nicht mehr um die Speicherverwaltung kümmern müsstest.



  • Da _CrtCheckMemory kein Standard-C++ ist kann ich jetzt nur wilde Vermutungen anstellen was es macht und warum es vielleicht Probleme hat:

    Nach der Ausgabe sind da 4 Werte im Speicher, die alle direkt hintereinander sitzen und alle den Wert 0 haben, aber 0xFD erwartet wird. Ich hab mal nach CrtCheckMemory gegooglet und dieses Wunderwerk an gebabelfischtem Ex-Englisch gefunden: http://support.microsoft.com/kb/833608/de
    Man kann dort mit etwas Mühe herausinterpretieren, dass CrtCheckMemory bei neu allokiertem Memory eine 0xFDFDFDFD-Belegung erwartet, malloc diese aber nur liefert wenn man vorher _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF); aufruft (musst also das alloc_mem_df-Flag mit deinen anderen Flags verodern).



  • Ich habe es dann doch mit malloc und free aufgegeben, weil der VC6.0-Compiler grundsätzlich ein Problem damit hat.

    Ich bin dann doch auf die Variante mit Strings und Vektoren umgestiegen - auch wenn das bedeutet, dass etwas Speicher verschwendet wird.



  • lunatic82 schrieb:

    VC6.0-Compiler

    Uh. Hättest du das Ding schon früher erwähnt dann wär der Thread nicht so lang geworden. Der VC6 hat mit vielen Dingen ein Problem und ist ein ziemlicher Krampf. Wenn wir das gewusst hätten dann hättest du 5 Posts á la "besorg dir einen aktuellen, ordentlichen Compiler" bekommen und keine Hilfsversuche - die sind bei VC6 nämlich häufig allzu fruchtlos.



  • Im Unternehmen verwenden wir den leider und deswegen bin ich darauf angewiesen 😞

    Privat würde ich den nie benutzen...



  • lunatic82 schrieb:

    ...Ich bin dann doch auf die Variante mit Strings und Vektoren umgestiegen - auch wenn das bedeutet, dass etwas Speicher verschwendet wird.

    Keine Sorge: Der wird nicht im Hinterhof verbrannt. Den bekommst Du wieder und dort werden auch nicht die Lottozahlen vom letzten Jahr eingetragen, sondern Informationen, die zur Speicherverwaltung und/oder zur Performanceoptimierung nötig sind - sprich: Die Du höchstwahrscheindlich ebenfalls irgendwo abgelegt hättest. 😉

    Gruß,

    Simon2.



  • Das stimmt natürlich, bei dem nackten C-Code isst es aber etwas weniger Overhead. Ist aber aucch egal, denn es funktioniert ja nun und sieht auch mehr nach C++ aus. 🙂

    Trotzdem werden wir uns hier langfristig mal einen anderen Compiler zulegen müssen - vor allem wenn es die Mitarbeiter weniger Nerven kostet.



  • lunatic82 schrieb:

    Das stimmt natürlich, bei dem nackten C-Code isst es aber etwas weniger Overhead.

    Was zu beweisen wäre. Dafür müsstet du ja erst einmal funktionierenden Code geschrieben haben, um das überhaupt messen zu können. Kaputten Code mit Funktionierendem zu vergleichen ist nicht sinnvoll.

    Wenn du mal den "Overhead" misst, den du durch dein Gefrickel erzeugt hast - also die Zeit die unnötigerweise dafür drauf ging, den ursprünglichen Code zu debuggen - dürfte es deinen Arbeitgeber teurer gekommen sein, dich für diese verplemperte Zeit zu bezahlen, als wenn du es gleich RichtigTM gemacht hättest.



  • Registrierter Troll schrieb:

    Wenn du mal den "Overhead" misst, den du durch dein Gefrickel erzeugt hast - also die Zeit die unnötigerweise dafür drauf ging, den ursprünglichen Code zu debuggen - dürfte es deinen Arbeitgeber teurer gekommen sein, dich für diese verplemperte Zeit zu bezahlen, als wenn du es gleich RichtigTM gemacht hättest.

    Wenn er gut ist, kann er es so argumentieren dass vor allem der bescheuerte VC6 dran schuld ist. Dann wäre es für n guten Zweck verplempert 😉



  • Registrierter Troll schrieb:

    Wenn du mal den "Overhead" misst, den du durch dein Gefrickel erzeugt hast - also die Zeit die unnötigerweise dafür drauf ging, den ursprünglichen Code zu debuggen - dürfte es deinen Arbeitgeber teurer gekommen sein, dich für diese verplemperte Zeit zu bezahlen, als wenn du es gleich RichtigTM gemacht hättest.

    War ganz einfach zu beweisen, indem man den Code komplett unter g++ erstellt bzw. den Intel Compiler nutzt...

    Und vertane Arbeitszeit war das auch nicht. Wir mussten uns so mal mit den unterschiedlichen Speicherverwaltungen im Debug- und Release-Mode auseinander setzen, haben gelernt das der VC6.0-Compiler für den Arsch ist und werden nun auf Eclipse, CDT, Intel-Compiler umstellen.

    Fehlt nur noch ein gescheiter Debugger. Schön wäre so etwas wie das in XCode integrierte Frontendd für den gdb. Das ist echt praktiscch, hab ich aber für die Windows-Plattform noch nicht gefunden.

    Übrigens, gibt es keinen richtigen Weg. Die Methode, die ich gepostet habe, funktioniert schon seit Ewigkeiten auf meinem Mac und ist extra portabel gehalten.

    Dein std::string und std::vector bekommst Du ja niemals auf einem Embedded-System an den Start. Die meisten Compiler für diese Systeme kennen nämlich keine Strings.



  • lunatic82 schrieb:

    Übrigens, gibt es keinen richtigen Weg.

    In C++ mit malloc und free zu hantieren ist aber garantiert der FalscheTM.

    Die Methode, die ich gepostet habe, funktioniert schon seit Ewigkeiten auf meinem Mac und ist extra portabel gehalten.

    Uh, sorry, aber...

    arr = (char**)malloc(sg * sizeof(char*));
        [...]
      for(i=0; i <= sg; i++) {
        arr[i] = NULL;
        [...]
      }
    

    Dieser Code ist einfach nur kaputt und wenn der jemals irgendwo funktionierte, dann war das pures Glück. Und das ist nicht die Schuld des Compilers, auch wenn du das gerne so hättest.

    Dein std::string und std::vector bekommst Du ja niemals auf einem Embedded-System an den Start.

    Nochmal sorry, aber WTF? Warum wurde dann überhaupt C++ gewählt, wenn die Plattform noch nicht einmal das Minimum hergibt?



  • lunatic82 schrieb:

    Wir mussten uns so mal mit den unterschiedlichen Speicherverwaltungen im Debug- und Release-Mode auseinander setzen, haben gelernt das der VC6.0-Compiler für den ***** ist und werden nun auf Eclipse, CDT, Intel-Compiler umstellen.

    Durchaus positiver Effekt 😉 \o/



  • Registrierter Troll schrieb:

    Dieser Code ist einfach nur kaputt und wenn der jemals irgendwo funktionierte, dann war das pures Glück. Und das ist nicht die Schuld des Compilers, auch wenn du das gerne so hättest.
    [...]
    Nochmal sorry, aber WTF? Warum wurde dann überhaupt C++ gewählt, wenn die Plattform noch nicht einmal das Minimum hergibt?

    Ja der Code ist kaputt, aber es kommt drauf an, was der Compiler damit macht. Sind die Optimierungen aus, dann funktioniert es problemlos...

    Du kennst den Rest der Software nicht, der in C++ geschrieben ist. Warum sollte ich eine Funktion, die bereitss existiert noch einmal neu schreiben... Da ist nur die Klassendefinition drum gepackt worden.


Anmelden zum Antworten