Hallo,
(mein Problem ist ein wenig OT, aber sehr wichtig fuer mich.)
Ich bekomme folgende Fehlermeldung beim Ausfuehren meines C-Programms: --- Program received signal SIGBUS, Bus error. 0xff2c607c in t_delete () ---
Der Backtrace sieht folgendermaszen aus: --- (gdb) bt #0 0xff2c607c in t_delete () #1 0xff2c575c in _malloc_unlocked () #2 0xff2c55bc in malloc () #3 0x1f6c8 in createNewActionSetRep (initVal=-1) at my_planner.c:29 ... ---
Meine Funktion createNewActionSetRep() ruft malloc() auf. Die Funktion wird aufgerufen, wenn eine (alte) Instanz einer Struktur geloescht wurde und eine neue benoetigt wird, und zwar kurz darauf. Die Allokierung eines neuen Speicherbereiches (gleichen Typs, Groesze) schlaegt fehl, aber auch nur manchmal, da die Funktion bereits vorher ein paar Mal benutzt worden ist. Der betreffende Sourcecode ist hier skizzenhaft dargestellt:
--- struct S { int foo; } *sp;
/* die Allokierung erfolgt eigentlich in createNewActionSetRep() */ sp = (struct S *) malloc(sizeof(struct S)); free(sp); /* ein paar wenige Anweisungen */ sp = (struct S *) malloc(sizeof(struct S)); ---
Eine Suche im Internet hat nichts weiter als allgemeine Kommentare ergeben, unter anderem, dasz das Problem manchmal auftritt, wenn man denselben Pointer mehrmals free()-ed. Aber der Fall tritt hier nicht ein.
Ich bin fuer jeden Hinweis dankbar, da es wichtig und dringend ist.
Eine dazugehoerige Frage: Wie kann ich statt malloc(3C) die Funktion malloc(3X) benutzen, wie teile ich das dem Compiler mit und wie kann ich das im Objektcode nachpruefen, welche Funktion tatsaechlich benutzt wird?
Infos zur Umgebung: System: SunOS 5.7 Generic_106541-11 sun4u sparc SUNW,Ultra-5_10 Compiler: gcc 2.95.2 und cc (SPARCWorks-5.0/SUNWspro) probiert. #include <stdlib.h> Auch -lmalloc habe ich probiert.
Vielen Dank.
MfG Matthias. --- E-Mail: mf14@inf.tu-dresden.de
On Wednesday 15 August 2001 10:35, Matthias Fichtner wrote:
Hallo,
(mein Problem ist ein wenig OT, aber sehr wichtig fuer mich.)
Ich bekomme folgende Fehlermeldung beim Ausfuehren meines C-Programms:
Program received signal SIGBUS, Bus error. 0xff2c607c in t_delete ()
Der Backtrace sieht folgendermaszen aus:
(gdb) bt #0 0xff2c607c in t_delete () #1 0xff2c575c in _malloc_unlocked () #2 0xff2c55bc in malloc () #3 0x1f6c8 in createNewActionSetRep (initVal=-1) at my_planner.c:29 ...
SIGBUS ist da schonmal recht ungewöhnlich. Normalerweise verursacht malloc/free SIGSEGV.
Ohne Sourcen kann ich natürlich nur raten:
Versuch mal mit Einzelschritten ranzugehen. Ich hatte solche Probleme oft, wenn ich Schleifen und Verzweigungen falsch designt hatte. Evtl. geht er zu oft durch eine Schleife.
Sehr beliebt sind auch solche Fehler: int *a=malloc(80); //Zuweisung... for (;*a;a++)//tue irgendwas free(a);
Der Fehler: malloc alloziert (zumindest bei glibc) mehr Speicher, als angefordert. Ganz am Anfang speichert es seine Allozierungsliste, die erste Position dahinter wird zurückgegeben. Wenn ein Pointer an free übergeben wird zählt es also ein paar Byte zurück und erwartet dort seine eigenen Daten. In dem Fall oben wird es also auf Nutzerdaten statt auf seine eigenen Zugreifen und logischerweise fehlerhafte Werte bekommen.
Konrad
PS.: das ist im Übrigen keine SunOS Liste.
Hallo,
da ich aber nur Werte in der Struktur selbst aendere und nie den Pointer, wie in deiner Schleife, kann ich den Fall ausschlieszen, Auszerdem, ich glaube den Fall einer doppelten Freigabe des Speicherbereiches durch ein Flag im Speicherbereich, das dessen Freigabe anzeigt, ausgeschlossen zu haben.
MfG Matthias.
PS: ich weisz, was das fuer eine Liste ist. Entschuldigung. Mir faellt so schnell keine andere Moeglichkeit ein. Das Verfolgen der Liste hat aber gezeigt, dasz einige gute Programmierer eingeschrieben sind. --- E-Mail: mf14@inf.tu-dresden.de
On Wed, 15 Aug 2001, Konrad Rosenbaum wrote:
SIGBUS ist da schonmal recht ungewöhnlich. Normalerweise verursacht malloc/free SIGSEGV.
Ohne Sourcen kann ich natürlich nur raten:
Versuch mal mit Einzelschritten ranzugehen. Ich hatte solche Probleme oft, wenn ich Schleifen und Verzweigungen falsch designt hatte. Evtl. geht er zu oft durch eine Schleife.
Sehr beliebt sind auch solche Fehler: int *a=malloc(80); //Zuweisung... for (;*a;a++)//tue irgendwas free(a);
Der Fehler: malloc alloziert (zumindest bei glibc) mehr Speicher, als angefordert. Ganz am Anfang speichert es seine Allozierungsliste, die erste Position dahinter wird zurückgegeben. Wenn ein Pointer an free übergeben wird zählt es also ein paar Byte zurück und erwartet dort seine eigenen Daten. In dem Fall oben wird es also auf Nutzerdaten statt auf seine eigenen Zugreifen und logischerweise fehlerhafte Werte bekommen.
On Wednesday 15 August 2001 12:38, Matthias Fichtner wrote:
da ich aber nur Werte in der Struktur selbst aendere und nie den Pointer, wie in deiner Schleife, kann ich den Fall ausschlieszen, Auszerdem, ich glaube den Fall einer doppelten Freigabe des Speicherbereiches durch ein Flag im Speicherbereich, das dessen Freigabe anzeigt, ausgeschlossen zu haben.
Dein Glaube in allen Ehren. An Deiner Stelle würde ich es trotzdem gründlich debuggen. Im Gegensatz zu der Serie aus meiner Sig (s.u.) läuft Programmierung nicht nach dem Prinzip "Scotty, mach mal." - Fehler beseitigen heißt oft lange danach suchen und das bedeutet auch Sachen explizit auszuschließen, von denen man sich nicht vorstellen kann, dass sie die Fehlerquelle sind. Ganz besonders bei Fällen wie Deinen (wo man selbst keine Ideen mehr hat) sollten ersteinmal alle Standardfälle abgecheckt werden (Standardfehler sind kein Zeichen von Schwäche! Sie sind halt Standard.).
Sprich: das normale Vorgehen in solchen Fällen ist dieses: 1.Alle relevanten Variablen überwachen (Pointer, normaler Variablen, Inhalte von Pointern) und Schrittweise debuggen. 2.Wenn das nix bringt: den Radius erweitern (weitere Funktionen usw.). 3.Wenn das auch nix bringt: die relevanten Teile in ein vereinfachtes Programm übernehmen und solange testen, bis der Fehler reproduzierbar und lokalisierbar ist (evtl. ist es auch ein Bug in der Libc). Wenn man so weit ist: dringend alle Spezifikationen durchlesen, um sich Peinlichkeiten zu ersparen. Wenn die Situation nicht auf eigenen Fehlern beruht: Bugreport schreiben und nach einem Workaround suchen falls es länger dauern kann.
Konrad
On Wed, Aug 15, 2001 at 01:21:25PM +0200, Konrad Rosenbaum wrote: Hallo *,
Dein Glaube in allen Ehren. An Deiner Stelle würde ich es trotzdem gründlich debuggen. Im Gegensatz zu der Serie aus meiner Sig (s.u.) läuft
[SWT-Prosa gelöscht]
also ich fand Josephs Methode von vor ein paar Tagen besser. Bei nicht nachvollziehbaren Problemen wird einfach das Ticket aus dem Bug Tracking System gelöscht und die Welt läuft wieder rund. Das war einfach nur cool!
SCNR, Reinhard
Am Mittwoch, dem 15. August 2001 um 13:38:12, schrieb Reinhard Foerster:
also ich fand Josephs Methode von vor ein paar Tagen besser. Bei nicht nachvollziehbaren Problemen wird einfach das Ticket aus dem Bug Tracking System gelöscht und die Welt läuft wieder rund. Das war einfach nur cool!
Was machst Du denn bei Fehlern, die du nicht reproduzieren kannst?
Torsten
On Wed, Aug 15, 2001 at 01:50:53PM +0200, Torsten Werner wrote:
Am Mittwoch, dem 15. August 2001 um 13:38:12, schrieb Reinhard Foerster:
also ich fand Josephs Methode von vor ein paar Tagen besser. Bei nicht nachvollziehbaren Problemen wird einfach das Ticket aus dem Bug Tracking System gelöscht und die Welt läuft wieder rund. Das war einfach nur cool!
Was machst Du denn bei Fehlern, die du nicht reproduzieren kannst?
Ähm, obiges von mir war kein Scherz. Ich fand das wirklich genial.
Reinhard (der sonst einen :-) angehängt hätte)
On Wednesday 15 August 2001 14:05, Reinhard Foerster wrote:
On Wed, Aug 15, 2001 at 01:50:53PM +0200, Torsten Werner wrote:
Am Mittwoch, dem 15. August 2001 um 13:38:12, schrieb Reinhard Foerster:
also ich fand Josephs Methode von vor ein paar Tagen besser. Bei nicht nachvollziehbaren Problemen wird einfach das Ticket aus dem Bug Tracking System gelöscht und die Welt läuft wieder rund. Das war einfach nur cool!
Was machst Du denn bei Fehlern, die du nicht reproduzieren kannst?
Ähm, obiges von mir war kein Scherz. Ich fand das wirklich genial.
Würdest Du das durchgerostete Bodenblech eines Autos auch mit Plakatfarbe behandeln und das Auto dann für repariert erklären?
Konrad
On Wed, Aug 15, 2001 at 04:04:59PM +0200, Konrad Rosenbaum wrote:
Würdest Du das durchgerostete Bodenblech eines Autos auch mit Plakatfarbe behandeln und das Auto dann für repariert erklären?
Klar doch. Ich würde lediglich die Schweinerei mit der Farbe weglassen. Warum sollte man mit Spielzeugautos anders verfahren, als mit aus Spaß programmierter Software?
Die Welt besteht zum Glück nicht nur aus wichtigen Dingen, die man bis ins Innerste untersuchen muß. Genau das war bei Josephs ulkigem Bug der Fall und seine Reaktion deshalb so passend. Wenn du nun allerdings versuchst, dieses Lösungschema auf alle restlichen Probleme der Welt anzuwenden, _könntest_ du Probleme bekommen. Hätte ich das wirklich explizit dazuschreiben müssen?
... wir werden mal wieder OT
Reinhard
On Wed, Aug 15, 2001 at 12:09:23PM +0200, Konrad Rosenbaum wrote:
int *a=malloc(80); //Zuweisung... for (;*a;a++)//tue irgendwas free(a);
Sehr beliebt? In der 2. Woche C, danach eigentlich nicht mehr, oder?
PS.: das ist im Übrigen keine SunOS Liste.
Nitpicker.
Das war's, was ich sagen wollte.
Heiko
On Wednesday 15 August 2001 21:00, Heiko Schlittermann wrote:
On Wed, Aug 15, 2001 at 12:09:23PM +0200, Konrad Rosenbaum wrote:
int *a=malloc(80); //Zuweisung... for (;*a;a++)//tue irgendwas free(a);
Sehr beliebt? In der 2. Woche C, danach eigentlich nicht mehr, oder?
komisch, ich mach' das andauernd. Meist sehen die Auswertungen noch gemeiner und die Schleifen wesentlich unleserlicher aus.
Ich sag' nur: lineare Suche. (B-Trees und Hashes sind für die meisten Fälle zu kompliziert)
Konrad
On Wed, Aug 15, 2001 at 09:35:41AM +0100, Matthias Fichtner wrote:
struct S { int foo; } *sp;
/* die Allokierung erfolgt eigentlich in createNewActionSetRep() */ sp = (struct S *) malloc(sizeof(struct S)); free(sp); /* ein paar wenige Anweisungen */ sp = (struct S *) malloc(sizeof(struct S));
Da ist natürlich nix falsch dran. Entweder hast den zum Fehler führenden Teil nicht gemailt oder was anderes is kaputt (Hardware insb. RAM)
System: SunOS 5.7 Generic_106541-11 sun4u sparc SUNW,Ultra-5_10
Achso, falsches OS :-) Aber die Kisten bemerken kaputten RAM eigentlich. Was passiert auf einem anderen Rechner mit deinem Programm?
Reinhard
ps: da hat jemand schon lange keine OS-Patches mehr installiert
Hallo,
Matthias Fichtner msc69mxf@cs.bham.ac.uk schrieb:
Eine Suche im Internet hat nichts weiter als allgemeine Kommentare ergeben, unter anderem, dasz das Problem manchmal auftritt, wenn man denselben Pointer mehrmals free()-ed. Aber der Fall tritt hier nicht ein.
Der Fehler kann auch auftreten, wenn man nach free() in den schon freigegebenen Bereich hineinschreibt. Der libc steht es frei, in solchen Bereichen Verwaltungsinformationen zu halten, und wenn die jemand zerstoert, geht irgendein malloc() in die Hose.
Holger
Hallo,
mein Problem hat sich durch das Hinzufuegen und Verwalten eines Flags in jedem Speicherbereich, das angibt, ob ich den Bereich noch benutzen darf, geloest. Scheinbar kann man mit free() freigegebene Bereiche noch lesen---das nutze ich aus. Nun funktionierts (, glaube ich. :) )
On Wed, 15 Aug 2001, Holger Dietze wrote:
Der Fehler kann auch auftreten, wenn man nach free() in den schon freigegebenen Bereich hineinschreibt. Der libc steht es frei, in solchen Bereichen Verwaltungsinformationen zu halten, und wenn die jemand zerstoert, geht irgendein malloc() in die Hose.
Genau das war der Grund. Schande auf schlampige Programmierer. ;-) (Zeitdruck)
Danke an alle.
Matthias.
On Wednesday 15 August 2001 22:11, Matthias Fichtner wrote:
Hallo,
mein Problem hat sich durch das Hinzufuegen und Verwalten eines Flags in jedem Speicherbereich, das angibt, ob ich den Bereich noch benutzen darf, geloest. Scheinbar kann man mit free() freigegebene Bereiche noch lesen---das nutze ich aus. Nun funktionierts (, glaube ich. :) )
Dass man das noch lesen kann ist nicht immer so. Das kommt ganz auf das Verhalten der jeweiligen Implementation von malloc und die Position des Speicherbereichs an. Manchmal wird der Block auch sofort freigegeben (wenn es der letzte allozierte Speicher auf dem Block war) und das bedeutet, dass die Adresse ungültig wird - Folge: SIGSEGV.
Die einfachste Grundregel für solche Situationen: setze den Pointer auf NULL, wenn er freigegeben wurde. Dann bekommt man bei _jedem_ Test ein SEGV und stößt schneller auf verbliebene Logikfehler.
Konrad
Matthias Fichtner msc69mxf@cs.bham.ac.uk schrieb:
mein Problem hat sich durch das Hinzufuegen und Verwalten eines Flags in jedem Speicherbereich, das angibt, ob ich den Bereich noch benutzen darf, geloest. Scheinbar kann man mit free() freigegebene Bereiche noch lesen---das nutze ich aus. Nun funktionierts (, glaube ich. :) )
Meistens klappt das Lesen aus einem freigegebenen Bereich(*). Allerdings kann man sich auf den gelesenen Wert nicht verlassen, moeglicherweise hat die Speicherwaltung dort schon was reingeschrieben oder den Bereich sogar schon wieder zur Verwendung ausgegeben.
(*) GNU libc gibt den Speicher ans OS zurueck, wenn er entweder mit mmap() geholt wurde (kommt nur bei relativ grossen Anforderungen vor) oder durch das free() der freie zusammenhaengende Bereich am oberen Ende eine bestimmte Groesse ueberschreitet. Bei anderen malloc/free-Implementationen duerfte das aehnlich ablaufen. Die kritischen Groessen sind bei der GNU libc uebrigens einstellbar (RTFM).
Holger
lug-dd@mailman.schlittermann.de