[C++] [Linux] Valgrind meldet seltsame Memoryfehler

Miq

Grünschnabel
Liebe Experten,

(Sorry, etwas längere Vorgeschichte zur Erklärung)

ich habe seit einigen Jahren ein C++-Programm am Wickel, das aus einigen 1000 Sourcezeilen besteht. Es wurde bisher unter Linux 2.4 und Solaris 8 compiliert, jeweils mit gcc 3.3. Läuft unter beiden OSsen auch prächtig und ohne Symptome.
Jetzt will ich das Programm mit MinGW unter Windows bauen. Das Compilieren geht auch ohne Fehlermeldung, trotz "-W -Wall". Beim Ausführen unter WinXP knallt es aber sofort am Start mit einer SIGSEGV. gdb hilft nicht weiter, deswegen habe ich auf Anraten eines Bekannten unter Linux mal valgrind darauf angesetzt (Version 2.2).
Valgrind liefert jetzt Fehlermeldungen, die ich schlicht nicht verstehe - sprachlich schon, inhaltlich nicht. Z.B. ist die allererste Anweisung nach "main(..." die hier:

unsigned int MAXTEST=1000;

und darüber motzt valgrind schon:

==4138== Invalid write of size 4
==4138== at 0x804ED59: main (runner.cc:22)
==4138== by 0x4030E856: __libc_start_main (in /lib/libc.so.6)
==4138== by 0x8049140: (within /home/micha/e5/runner)
==4138== Address 0xBFFFF32C is not stack'd, malloc'd or free'd

Außerdem wird jede Zeile moniert, die eine der strxxx()- bzw. memxxx()-Standardfunktionen aufruft. Da ist dann die Meldung

==4084== Invalid read of size 4
==4084== at 0x8050266: (within /home/micha/e5/runner)
==4084== by 0x1BA12856: __libc_start_main (in /lib/libc.so.6)
==4084== by 0x8049120: (within /home/micha/e5/runner)
==4084== Address 0x5290FE14 is on thread 1's stack

Statt "read" gibt's natürlich auch "write" in der ersten Zeile dieses Meldungsblocks. Da das Programm willentlich keinerlei Threads benutzt, bin ich auch hier etwas konsterniert...:(

Kann mir jemand das Phänomen erklären, bitte?

Ciao, Miq.
 
Hallo,

==4084== Invalid read of size 4
==4084== at 0x8050266: (within /home/micha/e5/runner)
==4084== by 0x1BA12856: __libc_start_main (in /lib/libc.so.6)
==4084== by 0x8049120: (within /home/micha/e5/runner)
==4084== Address 0x5290FE14 is on thread 1's stack

helfen kann ich dir leider auch nicht, da ich dein Programm nicht kenne,
aber schau genau ob du vielleicht aliase (also 2 Pointer auf ein und
dasselbe Objekt) zweimal freigibst. Solche Fehler sind meistens nicht
offensichtlich aus dem Code da ja die Pointer unterschiedliche Namen
haben. Aber wenn du jeden Pointer freigibst veruschst du das Objekt
doppelt freizugeben, das kann gut gehen oder auch nicht, ist aber
trotzdem immer ein Fehler ;)

Und schau bitte auch genau ob du alle Speicher die du dir via malloc geholt
hast wieder freigibst, der erste Fehler sieht so aus als hättest du
ein leak irgendwo. Ich kann mir nicht vorstellen das der Fehler in der von dir
geschreibenen Zeile ist.

Ich hoffe ich konnte dir helfen, vielleicht suchst du auch mal im inet
nach nem Howto wo alle Fehlermeldungen mal genauer erklärt werden.

Gruß

RedWing
 
Danke schön für die Antwort!

Da die angemoserte Zeile effektiv die erste in main ist, passiert zumindest da nichts Pointer-mäßiges vorher, außer vielleicht in ein paar static-Memberinitialisierungen in einer der verwendeten Klassen, aber das sind alles nur int's. Seltsamerweise ist der erste Fehler weg, wenn ich die alternative Syntax

unsigned int MAXTEST(1000);

verwende - C++-konform ist beides, und gcc übersetzt es ja auch, aber nur die erste Variante wird von valgrind bemängelt.

Und die weiteren Fehler von wegen "Address 0x5290FDC0 is on thread 1's stack"
könnten mit dieser Warnung am Anfang zusammenhängen:

Warning: client switching stacks? %esp: 0x52BFE35C --> 0x5290FDD0

Nur warum?
 
Kannst du evtl die entsprechenden Zeilen + 5 Zeilen drunter/drüber mal hier posten ? Dann könnte man evtl besser was mit deinen Fehlermeldungen anfangen.

Gruss

MFC OpenGL
 
Danke für Eure Hilfe, aber das Thema hat sich geklärt. Eine Expertin in der valgrind_users Mailing list hat mich auf die richtige Fährte gesetzt.

Die Zeile "unsigned int MAXTEST(1000);" ist im Prinzip die Schuldige, denn MAXTEST ist eine DImension eines float-Arrays, das ein ganzes Stück weiter unten im Sourcecode deklariert wird. Da aber MAXTEST sich nie ändert, zieht der Compiler die Deklaration offensichtlich ganz nach vorne, so dass sie so ziemlich als Erstes im Programm ausgeführt wird.
Das Array ist sehr groß, nämlich MAXTEST*256*sizeof(float), also ein knappes MB. Und da liegt das Problem:
- valgrind rechnet mit so großen Allozierungen nicht und interpretiert das als Threadwechsel, wodurch die weiteren Fehlermeldungen provoziert werden.
- unter Windows gibt es keine so großen, zusammenhängenden Speicherblöcke, so dass dadurch dann der SIGSEGV erzeugt wird.
 
Zurück