"Christmas - the time to fix the computers of your loved ones" « Lord Wyrm

Fehelermeldungen beheben?

Qualle 30.07.2007 - 21:36 3613 24 Thread rating
Posts

Armax

OC Addicted
Registered: Apr 2004
Location: .
Posts: 1058
Ich benutz jetzt einfach mal diesen Thread um einen alten C-Dorn in meinen Programmierpfoten zu ziehen:

Wie zur Hölle beseitigt man
Code:
*** glibc detected *** double free or corruption
Fehler?

Ich hab mich WOCHEN damit rum geärgert diese Fehler zu beheben und hab's dann aus Frust nur durch entfernen der free(); Anweisungen geschafft. Dadurch unterwarf sich aber das Programm der Wahrscheinlichkeitsrechnung: 2x starten -> funkt nit, 3tes mal funkts... Das soll's aber ja auch nit sein...
Gibts da irgendein debug-tool mit dem man zumindest auf die Ursache solcher Fehler kommen kann?

that

Moderator
Hoffnungsloser Optimist
Avatar
Registered: Mar 2000
Location: MeidLing
Posts: 11338
Zitat von Armax
Wie zur Hölle beseitigt man
Code:
*** glibc detected *** double free or corruption
Fehler?

Indem man für jedes Ergebnis von malloc() genau einmal free() aufruft und auch nicht irgendwohin in den Speicher schreibt wo man nicht darf.

Zitat von Armax
Gibts da irgendein debug-tool mit dem man zumindest auf die Ursache solcher Fehler kommen kann?

Mit einem normalen Debugger geht das meistens schon ganz gut. Außer dein Programm besteht aus 1000000 Zeilen, von denen die meisten nicht von dir sind. Für solche Fälle gibts schwerere Geschütze auch noch, z.B. Valgrind.

mat

Administrator
Legends never die
Avatar
Registered: Aug 2003
Location: nö
Posts: 25423
der numega boundschecker ist für solche zwecke bestens geeignet. gibts als visual studio plugin und stand-alone. das programm ist allerdings kostenpflichtig.

für neue projekte kannst du dir btw mit einem kleinen trick helfen: einfach statt malloc und free macros benutzen, zB SAFE_MALLOC und im debug modus wrapperfunktionen ansprechen, die per __LINE__ und __FILE__ debuginformationen in ein array speichert und bei zB SAFE_FREE diese wieder entfernt. am ende der ausführung checkst du dann einfach welche einträge noch im array stehen und tada: du hast deine memory leaks gefunden :)

würdest du übrigens c++ coden, dann kann dasselbe eine spur leichter mit dem überschreiben von new und delete operator erledigt werden.

Armax

OC Addicted
Registered: Apr 2004
Location: .
Posts: 1058
Zitat von that
Indem man für jedes Ergebnis von malloc() genau einmal free() aufruft und auch nicht irgendwohin in den Speicher schreibt wo man nicht darf.

Oh wie sehr hab ich das gemacht... was ich NIE verstanden habe ist, dass wenn man eine Variable/Zeiger (ja, ich hab noch imma schwierigkeiten damit) auf einen anderen Zeiger verweisen lässt, dass dann anscheinend auch den Vorherigen zeigt... für mich als (Java) Programmierer war/ist das total widersprüchlich und macht auch keinen Sinn... z.B. hab ich da Variablen ghabt bei denen ich mir absolut sicher war sie nur in einer abgeschlossen Funktion zu verwenden und hab dann just trotzdem wieder den Fehler eingheimst... und der Code war dabei noch absolut überschaubar...

@ mat: Reden wir hier von C oder C++? Prinzipiell wär ich eigentlich für kostenfreie, GPL Software dankbar die solche Fehler abcheckt...
beim Code Composer gibts z.B. ne Funktion bei der man die Speicherbereiche relativ schön überwachen kann... Gibts sowas unter C auch?

that

Moderator
Hoffnungsloser Optimist
Avatar
Registered: Mar 2000
Location: MeidLing
Posts: 11338
Zitat von Armax
was ich NIE verstanden habe ist, dass wenn man eine Variable/Zeiger (ja, ich hab noch imma schwierigkeiten damit) auf einen anderen Zeiger verweisen lässt, dass dann anscheinend auch den Vorherigen zeigt... für mich als (Java) Programmierer war/ist das total widersprüchlich und macht auch keinen Sinn...

In diesem Fall brauchst du erstmal kein Tool, sondern das grundlegende Verständnis für den Unterschied zwischen Variablen und Adressen, Namen, Referenzen und Werten.

Nico

former person of interest
Registered: Sep 2006
Location: -
Posts: 4082
call by value & call by reference gibts doch auch in java..

Armax

OC Addicted
Registered: Apr 2004
Location: .
Posts: 1058
Zitat von that
In diesem Fall brauchst du erstmal kein Tool, sondern das grundlegende Verständnis für den Unterschied zwischen Variablen und Adressen, Namen, Referenzen und Werten.

smells like teacher spirit... :p

Ich glaub aber du redest von komplett was anderem, deshalb is hier mein Problem ein bisschen genauer:
Prinzipiell versuch ich beim C Programmieren mit dynamischen Variablen immer an die Regel zu halten ein Array von unbestimmter Länge mit malloc() anzulegen und am Ende des Programms mit free() wieder freizugeben. Eigentlich sollte es logisch (bzw. leicht mit einer Suchfunktion überprüfbar) sein, dass man zu jeder mit malloc angelegten Variable nur ein free verwendet und somit is ein "double free"-Fehler eigentlich im Programmcode fast ausgeschlossen. AFAIK is aber die Krux an der Sache, dass wenn man nur mehrere dynamische Variablen verwendet und diese im Verarbeitungsprozess ihre Daten austauschen dass diese dann (anscheinend?) untereinander Verweise besitzen. Wenn man also a, b mit malloc angelegt hat, diese auf irgendeine schwindliche Weise Daten austauschen, kann es sein, dass ich zwar free(a) funktioniert, aber bei free(b) der "double free" fehler auftritt. und DASS leuchtet mir einfach nicht ein, wie sowas überhaupt sein kann... Deshalb hätt ich mir vorgestellt, dass es vl. ein Tool gibt, dass Verweise zwischen Variablen aufzeigt.

P.S.: Ich hab schon einige Beispiel C-Codes gesehen, die auf ein abschließendes free im Programm anscheinend pfeiffen... is das vl. so, dass bei Aufruf von exit() sowieso der gesamte vom Programm beanspruchte Speicherbereich freigegeben wird?

gue

Addicted
Avatar
Registered: Feb 2003
Location: Linz
Posts: 400
Huch, nein.
Wenn du ein Speicherobjekt mit malloc anlegst, dann liefert dir malloc einen Zeiger auf dieses Objekt (ein Zeiger ist nichts anderes als die Adresse, an der das Objekt liegt). Wenn du diesen Zeiger "duplizierst", also einer anderen Zeigervariable zuweist und dann beide freizugeben versuchst, erhälst du dieses ominöse double-free.
Beispiel:
Code: PHP
char *a = malloc(100);
char *b = a;
// a und b zeigen beide auf die selbe Stelle im Speicher
free(a); // ok
free(b); // Double free, da das Objekt, 
            //auf das b zeigt schon freigegeben ist
Wenn du deinen Speicher eh nur am Ende des Programms freigibst, dann kannst du auf das free() eigentlich verzichten (da das Betriebssystem sowieso den gesamten Speicher, der von dem Programm eingenommen wurde freigibt). Das ist aber nur für kleine Programme möglich/rentabel, die nicht lange laufen sollen (z.B. CLIs).
So ein double free ist übrigens sehr gefährlich da es an ganz anderen Stellen Fehler verursachen kann.
Z.B. hier:
Code: PHP
char *a = malloc(100);
char *b = a;
char *c;
free(a);
c = malloc(100);
// Jetzt zeigen b und c unter Umständen auf das selbe
// Objekt (hängt vom Allokator ab)
free(b);
// Objekt@c wurde freigegeben!

mat

Administrator
Legends never die
Avatar
Registered: Aug 2003
Location: nö
Posts: 25423
Zitat von Armax
@ mat: Reden wir hier von C oder C++? Prinzipiell wär ich eigentlich für kostenfreie, GPL Software dankbar die solche Fehler abcheckt...
beim Code Composer gibts z.B. ne Funktion bei der man die Speicherbereiche relativ schön überwachen kann... Gibts sowas unter C auch?
wir reden von C, sonst würde ich das wort malloc gar nicht in den mund nehmen :p

prinzipiell würde ich dir raten währenddessen du deine fähigkeiten schärfst, eine kleine library von eigenem code daneben aufzubauen, die mit jedem kleinen pimperlprojekt wächst. klarerweise hättest du atm gerne eine blackbox für diverse funktionen.. das spielt es aber nur selten, auch fremdcode und externe tools brauchen genügend verständnis vom handwerk - in diesem fall die sprache C. also, scheu dich nicht und stürz dich ins gefecht, deine library braucht debugging code :)

Marcellus

OC Addicted
Avatar
Registered: Mar 2005
Location: ~
Posts: 1755
http://www.pronix.de/pronix-756.html <= bringt dir das vllt was?
Kontakt | Unser Forum | Über overclockers.at | Impressum | Datenschutz