Johanna: Spielt der GCC verrückt?

Hallo,

ich zerbreche mir seit 16 Stunden den Kopf über folgende Simple Meldung, die erscheint wenn mein Programm abstürzt. Dabei habe ich schon mindestens 2 Kannen Kaffee und 3 Cola-Flaschen in mich hineingekippt.

1: "Josef"
2: main.h: 10097(0x8eb4890[])
3: main2.h: 21(0x8eb4880)
4: "Maria"
5: main.h: 10097(0x8eb4870[])
6: *** glibc detected *** ./main: free(): invalid pointer: 0x08eb4860 ***
7: ======= Backtrace: =========
8: /lib/i686/nosegneg/libc.so.6[0x26b9b1]
9: /lib/i686/nosegneg/libc.so.6(cfree+0x90)[0x26f060]
10: /usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0x5b48091]

Das sind die letzten Lebenszeichen meines Programms. Ich will nun die Ausgabe anhand von Codestücken erklären.

Zeile 1,2 4,5 sind vom gleichen Code:

  
// Die beiden Makros  
  
#define SAFE_DELETE(p)       if(p != NULL) { delete   p; printf("%s: %d(%p)\n", __FILE__, __LINE__, p); p = NULL; }  
  
#define SAFE_DELETE_ARRAY(p) if(p != NULL) { delete[] p; printf("%s: %d(%p[])\n", __FILE__, __LINE__, p);  p = NULL; }  
  
// Die printf-Ausgabe wurde nur zu Debug-Zwecken eingefügt.  
  
void clear(void) // clear() ist eine Methode  
{ // String ist vom Typ char* und wurde auf dem Heap angelegt  
  // Length ist vom Typ unsigned long long und beeinhaltet die Länge  
  // von String einschließlich dem abschließenden \0  
  if(Length == 1) {  
   SAFE_DELETE(String);  
  } else if(Length > 1) {  
   printf("%s\n", String); // Die Ausgabe Z. 1 u. 4  
   SAFE_DELETE_ARRAY(String); // Z. 2 u. 5.  
  }  
  String = NULL;  
  Length = 0;  
}  
  
// Die clear Methode wird hier aufgerufen  
for(unsigned long long i = 0; i < Length; i++) {  
 Tmp = List;  
 if(Tmp != NULL) {  
  printf("%d/%d %p: %s=%s\n", (int)i, (int)Length, Tmp,  Tmp->Label->get(),Tmp->Data->get() );  
  SAFE_DELETE(Tmp);  
 }  
 List = List->Next;  
 if(List == NULL) {  
  break;  
 }  
}  
// Hier wird eine Liste gelöscht  
// Tmp ist ein Zeiger auf ein Listen Element  
// und List ist ein Zeiger auf das Erste Element der Liste  
// Length die Länge der Liste(Anzahl der Elemente)  

Was mich besonders stutzig macht ist die Ausgabe die mein Programm macht und die Ausgabe die beim Absturz generiert wird.
"0x08eb4860" Diesen Wert hat angeblich mein invalider pointer.
Aber mein Programm sagt der Pointer hat die Adresse 0x08eb4870 bekommen und gibt zum Beweis auch noch den Inhalt des Arrays aus. Also muss die Adresse stimmen.

Wer macht hier den Murks? GCC oder Ich.
Habe ich alle relevanten Codeteile gepostet? Fehlen Erklärungen? Ja, eine fehlt mindestens. Nämlich eine Erklärung die ich mir von eurer Seite erbitte/erbete um diesem Spuk eine Ende zu bereiten.

Johanna

  1. #define SAFE_DELETE(p)       if(p != NULL) { delete   p; printf("%s: %d(%p)\n", __FILE__, __LINE__, p); p = NULL; }

    #define SAFE_DELETE_ARRAY(p) if(p != NULL) { delete[] p; printf("%s: %d(%p[])\n", __FILE__, __LINE__, p);  p = NULL; }

    Meiner Meinung nach schon zu viel Code für Makros..., aber das nur man Rande.

    Habe ich alle relevanten Codeteile gepostet? Fehlen Erklärungen?

    Ja, mir ist zum Teil nicht klar, wo die Variablen herkommen. Ich vermute mal, dass die global sind.

    Falls du Webspace zur Verfügung hast, könntest du ja mal den kompletten Code bereitstellen.

    Gruß

    Stareagle

    1. Ja, mir ist zum Teil nicht klar, wo die Variablen herkommen. Ich vermute mal, dass die global sind.

      Beides sind Methoden, also auch Alle Variablen sind private in den Klassen.

      Die Erste Methode clear() ist von einer String Klasse die das selbe wie std::string macht.

      Das zweite ist auch ein Teil einer clear() Methode die eine Liste löscht.

      In diesem Fall hat die List String-Klassen Elemente.

      Wiso ist das eigentlich so wichtig wo die Variablen herkommen?
      Von welchem Typ sie sind habe ich doch angegeben?
      Wenn die Variablen im Code nicht Lokal sind sind sie privat in der Klasse. Globale Variablen vermeide ich in Klassen.

      Johanna

      1. Sorry, ich hatte wegen gcc angenommen, dass es um C geht und nicht um C++.

        Versuch doch mal was passiert, wenn g++ zum kompilieren benutzt.

        Gruß

        Stareagle

        1. Versuch doch mal was passiert, wenn g++ zum kompilieren benutzt.

          Erwartest du wirklich ein anderes Ergebnis beim gleichen Compiler?

          Soviel ich weiss würde selbst gcc in vielen Fällen erkennen das es sich um C++ handelt und intern C++ übersetzen anstatt C oder zumindest eine paar Warnungen und Fehler ausgeben. Vieles was in C++ konform ist ist in C illegal.

          Meine Makefile:

          main: main.cpp
           /usr/bin/g++ -Wall -v -g3 -o /usr/main/bin/main /usr/main/main.cpp

          Also das war ein nicht sehr hilfreicher Vorschlag ...
          -bash-3.2$ rpm -qa | grep gcc
          libgcc-4.1.2-27.fc7
          gcc-java-4.1.2-27.fc7
          gcc-c++-4.1.2-27.fc7
          gcc-objc++-4.1.2-27.fc7
          avr-gcc-4.1.2-4.fc7
          gcc-4.1.2-27.fc7
          avr-gcc-c++-4.1.2-4.fc7
          gcc-objc-4.1.2-27.fc7

          Das habe ich alles installiert wie man sieht.

          Ich habe wie ich gerade sehe vergessen zu erwähnen das ich C++ code.
          Sorry.

          Johanna

      2. Wiso ist das eigentlich so wichtig wo die Variablen herkommen?
        Von welchem Typ sie sind habe ich doch angegeben?

        Es ist deshalb wichtig, weil das Programm
        bis jetzt ja noch nicht richtig funktioniert.

        In Deiner clear()-Methode wird - je nach Stringlänge -
        entweder delete oder delete[] auf den Pointer
        losgelassen, obwohl der in beiden Fällen
        vom Typ char* sein soll (so zumindest gemäß den
        Kommentaren). Wichtig wären daher zumindest die
        Stellen im Quelltext, an denen die Strings im Speicher
        erzeugt werden.

        Viele Grüße

        Andreas