Hallo, ich hoffe, mein Problem ist heir nicht OT. Ich schreibe an ein Programm in C, in das ich auch eine grosse Anzahl von Worten sortiere. Ich will das gerne mit einem Binaerbaum machen. Der Code- teil unten funktioniert auf einem Debian System mit gcc-3.2.1 und glibc-2.3.1 ohne Probleme. Ich kann sogar einen kompletten Bibel Text damit sortieren. Es wird einfach jedes Wort mit insert_item(Node *root, char* word) eingefuegt. Den Fehler kann man mit dem Code am Ende der Mail reproduziern. Auf einer SuSE 8.1 (gcc-3.2, glibc-2.2.5) und auch auf einer SuSE 6.4 (gcc-2.95.2, glibc-2.1.3) loest die Funktion new_node einen Segmentation Fault in glibc aus. Gdb sagt chunk_free () from libc.so.6 chunk_alloc () from libc.so.6 malloc () from libc.so.6 new_node () from tree-c:182 Ich bin noch Beginner in C und wuerde mich sehr ueber einen Hinweis freien. Terje struct node { char *val; int count; struct node *left; struct node *right; }; typedef struct node Node; Node *root; Node *new_node() { Node *elem; elem = malloc(sizeof(Node)); <--- immer hier elem->count = 0; return(elem); } void insert_item(Node *n, char *c) { int cmp; if( n->val == NULL ) { n->val = malloc(strlen(c)); strcpy(n->val,c); return; } cmp = strcmp(n->val, c); if(cmp > 0) { if(n->left == NULL) n->left = new_node(); insert_item(n->left, c); return; } else if(cmp < 0) { if(n->right == NULL) n->right = new_node(); insert_item(n->right, c); } else { n->count++; } } ______________________________________________________ Få den nye Yahoo! Messenger på http://no.messenger.yahoo.com/ Nye ikoner og bakgrunner, webkamera med superkvalitet og dobbelt så morsom
Hi, Die Meldungen chunk_free () from libc.so.6 chunk_alloc () from libc.so.6 malloc () from libc.so.6 new_node () from tree-c:182 treten meistens auf wenn an einer anderen Stelle die interne Speicherverwaltung von malloc ueberschrieben wird. Probier mal export MALLOC_CHECK_=1 oder export MALLOC_CHECK_=2 ( näheres man malloc ) auf der shell und starte Dein Programm nochmal. Meist bekommst du Meldungen die Dir zeigen an welcher Stelle Du deinen Speicher ueberschreibst. Gruss Erik Terje Fåberg wrote:
Hallo,
ich hoffe, mein Problem ist heir nicht OT. Ich schreibe an ein Programm in C, in das ich auch eine grosse Anzahl von Worten sortiere. Ich will das gerne mit einem Binaerbaum machen. Der Code- teil unten funktioniert auf einem Debian System mit gcc-3.2.1 und glibc-2.3.1 ohne Probleme. Ich kann sogar einen kompletten Bibel Text damit sortieren. Es wird einfach jedes Wort mit insert_item(Node *root, char* word) eingefuegt. Den Fehler kann man mit dem Code am Ende der Mail reproduziern.
Auf einer SuSE 8.1 (gcc-3.2, glibc-2.2.5) und auch auf einer SuSE 6.4 (gcc-2.95.2, glibc-2.1.3) loest die Funktion new_node einen Segmentation Fault in glibc aus. Gdb sagt
chunk_free () from libc.so.6 chunk_alloc () from libc.so.6 malloc () from libc.so.6 new_node () from tree-c:182
Ich bin noch Beginner in C und wuerde mich sehr ueber einen Hinweis freien.
Terje
struct node { char *val; int count; struct node *left; struct node *right; };
typedef struct node Node;
Node *root;
Node *new_node() { Node *elem; elem = malloc(sizeof(Node)); <--- immer hier elem->count = 0; return(elem); }
void insert_item(Node *n, char *c) { int cmp;
if( n->val == NULL ) { n->val = malloc(strlen(c)); strcpy(n->val,c); return; }
cmp = strcmp(n->val, c);
if(cmp > 0) { if(n->left == NULL) n->left = new_node(); insert_item(n->left, c); return; } else if(cmp < 0) { if(n->right == NULL) n->right = new_node(); insert_item(n->right, c); } else { n->count++; }
}
______________________________________________________ Få den nye Yahoo! Messenger på http://no.messenger.yahoo.com/ Nye ikoner og bakgrunner, webkamera med superkvalitet og dobbelt så morsom
On Sam, 14 Dez 2002 at 11:22 (+0100), Terje Fåberg wrote: [segfault] Ich weiss nicht, ob es die Ursache ist, aber ich sehe Probleme an folgenden Stellen:
struct node { char *val; int count; struct node *left; struct node *right; };
typedef struct node Node;
Node *root;
Du initialisierst root nicht, kannst also nicht sicher sein, dass da auch tatsächlich 0 drin steht. Besser: Node *root = NULL;
Node *new_node() { Node *elem; elem = malloc(sizeof(Node)); <--- immer hier
Hier sollte beim Compile eine Warnung kommen, da malloc() vom Typ void* ist. Besser einen typecast nutzen: elem = (Node *) malloc(sizeof(Node)); Initialisieren (Grund siehe unten): memset (elem, 0, sizeof (Node));
elem->count = 0;
Die Zeile kann entfallen, wenn Du per memset() initialisierst.
return(elem); }
void insert_item(Node *n, char *c) { int cmp;
if( n->val == NULL ) { n->val = malloc(strlen(c));
Hier ebenfalls einen typecast einsetzen und zusätzlich: Du reservierst hier IMHO zu wenig Platz, denn der nachfolgende strcpy kopiert das abschliessende NULL-Byte mit - überschreibt also nicht zu n->val gehörenden Speicher. n->val = (char *) malloc(strlen(c) + 1);
strcpy(n->val,c); return; }
cmp = strcmp(n->val, c);
if(cmp > 0) { if(n->left == NULL)
Diese Abfrage ist gefährlich, da Du n ja per malloc() erzeugt hast und malloc() den reservierten Speicher nicht initialisiert. Es ist nach einem malloc() also nicht sicher, dass die Pointer NULL sind. Abhilfe: Entweder nach dem malloc initialisieren (siehe oben) oder calloc() benutzen.
n->left = new_node(); insert_item(n->left, c); return; } else if(cmp < 0) { if(n->right == NULL)
Dito.
n->right = new_node(); insert_item(n->right, c); } else { n->count++; }
}
HTH Jan
Jan Trippler skrev:
Node *root;
Du initialisierst root nicht, kannst also nicht sicher sein, dass da auch tatsächlich 0 drin steht. Besser: Node *root = NULL;
Das hoert sich eigentlich logisch an. Aber ich habe mir mit den Data Display Debugger die Baumstrucktur visualisieren lassen. Auch die nicht initialisierten Zeiger enthalten NULL. Kann es sein, dass der gcc die Zeiger auch ohne explicite Angabe initialisiert?
elem = malloc(sizeof(Node)); <--- immer hier
Hier sollte beim Compile eine Warnung kommen, da malloc() vom Typ void* ist. Besser einen typecast nutzen: elem = (Node *) malloc(sizeof(Node));
Ich bekomme mit "-Wall -pedantic" ohne und mit Cast keine Warnung. Logisch wäre es aber.
if( n->val == NULL ) { n->val = malloc(strlen(c)); [...] zusätzlich: Du reservierst hier IMHO zu wenig Platz, denn der nachfolgende strcpy kopiert das abschliessende NULL-Byte mit -
Genau! Das hat der Lauf mit MALLOC_CHECK_=1 auch ergaben. Das ist wirklich meine Blindheit und Dumm- heit.
HTH Jan
Oh ja. Es hat geholfen. Vielen Dank! Terje ______________________________________________________ Få den nye Yahoo! Messenger på http://no.messenger.yahoo.com/ Nye ikoner og bakgrunner, webkamera med superkvalitet og dobbelt så morsom
Am Son, 2002-12-15 um 14.35 schrieb Terje Fåberg:
Jan Trippler skrev:
Node *root;
Du initialisierst root nicht, kannst also nicht sicher sein, dass da auch tatsächlich 0 drin steht. Besser: Node *root = NULL;
Das hoert sich eigentlich logisch an. Aber ich habe mir mit den Data Display Debugger die Baumstrucktur visualisieren lassen. Auch die nicht initialisierten Zeiger enthalten NULL. Kann es sein, dass der gcc die Zeiger auch ohne explicite Angabe initialisiert? Ja, zum Teil. Ist aber eigentlich Zufall, darauf verlassen darf man sich keinesfalls.
elem = malloc(sizeof(Node)); <--- immer hier
Hier sollte beim Compile eine Warnung kommen, da malloc() vom Typ void* ist. Besser einen typecast nutzen: elem = (Node *) malloc(sizeof(Node));
Ich bekomme mit "-Wall -pedantic" ohne und mit Cast keine Warnung. Logisch wäre es aber. Nein. Implizite Casts von void* nach typ* sind in C immer legal.
if( n->val == NULL ) { n->val = malloc(strlen(c)); [...] zusätzlich: Du reservierst hier IMHO zu wenig Platz, denn der nachfolgende strcpy kopiert das abschliessende NULL-Byte mit -
Genau! Das hat der Lauf mit MALLOC_CHECK_=1 auch ergaben. Das ist wirklich meine Blindheit und Dumm- heit. Bei der Gelegenheit: Schau dir mal strdup und calloc an.
Ralf
Hallo, da ja vor ein paar Tagen in einem anderen Thread zur Sprache kam, dass NULL nicht unbedingt durch ein Bitmuster aus lauter Nullen dargestellt wird, habe ich dazu noch eine kleine Frage im Zusammenhang mit memset. On Sunday 15 December 2002 13:03, Jan Trippler wrote: [...]
if(cmp > 0) { if(n->left == NULL)
Diese Abfrage ist gefährlich, da Du n ja per malloc() erzeugt hast und malloc() den reservierten Speicher nicht initialisiert. Es ist nach einem malloc() also nicht sicher, dass die Pointer NULL sind. Abhilfe: Entweder nach dem malloc initialisieren (siehe oben) oder calloc() benutzen. [...]
Wenn man mit calloc oder memset initalisiert und NULL haben will, dann ist diese Methode nicht portabel, oder? Ciao Sebastian
On Son, 15 Dez 2002 at 15:20 (+0100), Sebastian Huber wrote:
Hallo, da ja vor ein paar Tagen in einem anderen Thread zur Sprache kam, dass NULL nicht unbedingt durch ein Bitmuster aus lauter Nullen dargestellt wird, habe ich dazu noch eine kleine Frage im Zusammenhang mit memset.
Hm, ich kann mir ehrlich gesagt nicht vorstellen, was da sonst stehen soll. Ich habe die Diskussion am Rande mitgekriegt und würde schon gerne wissen, was bei einem Pointer auf eine Struktur sonst für ein Wert erscheinen soll.
On Sunday 15 December 2002 13:03, Jan Trippler wrote: [...]
if(cmp > 0) { if(n->left == NULL)
Diese Abfrage ist gefährlich, da Du n ja per malloc() erzeugt hast und malloc() den reservierten Speicher nicht initialisiert. Es ist nach einem malloc() also nicht sicher, dass die Pointer NULL sind. Abhilfe: Entweder nach dem malloc initialisieren (siehe oben) oder calloc() benutzen. [...]
Wenn man mit calloc oder memset initalisiert und NULL haben will, dann ist diese Methode nicht portabel, oder?
Siehe oben - ich habe noch kein Unix erlebt, bei dem das schiefgeht, lasse mich aber gern eines Besseren belehren (wenn ich erklärt kriege, warum das so sein soll ;-). Jan
Am Son, 2002-12-15 um 19.23 schrieb Jan Trippler:
On Son, 15 Dez 2002 at 15:20 (+0100), Sebastian Huber wrote:
On Sunday 15 December 2002 13:03, Jan Trippler wrote: [...]
if(cmp > 0) { if(n->left == NULL)
Diese Abfrage ist gefährlich, da Du n ja per malloc() erzeugt hast und malloc() den reservierten Speicher nicht initialisiert. Es ist nach einem malloc() also nicht sicher, dass die Pointer NULL sind. Abhilfe: Entweder nach dem malloc initialisieren (siehe oben) oder calloc() benutzen. [...]
Wenn man mit calloc oder memset initalisiert und NULL haben will, dann ist diese Methode nicht portabel, oder?
Siehe oben - ich habe noch kein Unix erlebt, bei dem das schiefgeht, Ich würde David's damalige Aussage bez. der Definition von NULL nicht unterschreiben, kann sie aber mangels Zugriff auf die 'C/C++'-Standards weder widerlegen noch bestätigen.
Ansonsten kenne kein System auf dem NULL nicht 0 ist, kenne aber diverse Software, die auf dieser Annahme basiert (Unter anderem basieren die GCC-libstdc++ und das gesamte X11-System darauf.)
lasse mich aber gern eines Besseren belehren (wenn ich erklärt kriege, warum das so sein soll ;-).
Wie gesagt, ich kenne kein System auf dem das nicht funktioniert. Ralf
Am Sonntag, 15. Dezember 2002 22:10 schrieb Ralf Corsepius: [...]
Ansonsten kenne kein System auf dem NULL nicht 0 ist, kenne aber diverse Software, die auf dieser Annahme basiert (Unter anderem basieren die GCC-libstdc++ und das gesamte X11-System darauf.)
lasse mich aber gern eines Besseren belehren (wenn ich erklärt kriege, warum das so sein soll ;-).
Wie gesagt, ich kenne kein System auf dem das nicht funktioniert.
Auch wenn ich blutiger Laie in Bezug auf C/C++ bin, aber ich denke, das kommt eigentlich aus der Mathematik, das NULL und 0 nicht gleich sind. 0 ist eine Zahl ohne Wert, NULL dagegen einfach nichts. In Datenbanken wird NULL als "Kein Inhalt vorhanden" angesehen, während 0 ja 0 ist (ein Wert). NULL wird doch auch als Leerstring, String ohne eine Länge, ohne Inhalt definiert (Prüfung auf chr(0), was schon die Definition von chr(0) als NUL zeigt). NULL und 0 muß man eigentlich als zwei getrennte Aussagen über den Zustand einer Variablen, eines Vektors etc. ansehen. Das NULL = 0 ist, müßte eigentlich dann vorher definiert sein, oder? Gruß Udo -- Mail: udo@neist.dnsalias.org oder udo.neist@t-online.de Hompage: http://neist.dnsalias.org
Hi @ all, Am Sonntag, 15. Dezember 2002 23:15 schrieb Udo Neist:
Auch wenn ich blutiger Laie in Bezug auf C/C++ bin, aber ich denke, das kommt eigentlich aus der Mathematik, das NULL und 0 nicht gleich sind. 0 ist eine Zahl ohne Wert, NULL dagegen
In java ist das AFAIK so, ich habe gerade "cat /usr/include/*.h | grep NULL" gemacht. Ich finde sehr häufig soetwas: #ifndef NULL #define NULL 0 oder #undef NULL #ifndef NULL #define NULL ((void *)0)
einfach nichts. In Datenbanken wird NULL als "Kein Inhalt vorhanden" angesehen, während 0 ja 0 ist (ein Wert). NULL wird doch auch als Leerstring, String ohne eine Länge, ohne Inhalt definiert (Prüfung auf chr(0), was schon die Definition von chr(0) als NUL zeigt). NULL und 0 muß man eigentlich als zwei getrennte Aussagen über den Zustand einer Variablen, eines Vektors etc. ansehen. Das NULL = 0 ist, müßte eigentlich dann vorher definiert sein, oder?
S.o, Du kannst NULL auch mit 31311231 definieren, wenn Du magst ;)) Aber das macht eigentlich nur Homer... Greetingx Andre
Ralf Corsepius skrev:
Ansonsten kenne kein System auf dem NULL nicht 0 ist, kenne aber diverse Software, die auf dieser Annahme basiert (Unter anderem basieren die GCC-libstdc++ und das gesamte X11-System darauf.)
Ich habe aus Interesse etwas gesucht und auch die folgenden Seite gefunden: http://bit.csc.lsu.edu/tutorial/ten-commandments/c-faq/c-1.html#1-14 Offensichtlich hat es ein paar Systeme gegaben, die nicht 0 als Null Pointer verwenden. Allerdings scheint davon nichts mehr annaehernd aktuell zu sein. Terje ______________________________________________________ Få den nye Yahoo! Messenger på http://no.messenger.yahoo.com/ Nye ikoner og bakgrunner, webkamera med superkvalitet og dobbelt så morsom
Hallo, On Sun, 15 Dec 2002, Ralf Corsepius wrote:
Am Son, 2002-12-15 um 19.23 schrieb Jan Trippler:
On Son, 15 Dez 2002 at 15:20 (+0100), Sebastian Huber wrote:
On Sunday 15 December 2002 13:03, Jan Trippler wrote: [...]
if(cmp > 0) { if(n->left == NULL)
Diese Abfrage ist gefährlich, da Du n ja per malloc() erzeugt hast und malloc() den reservierten Speicher nicht initialisiert. Es ist nach einem malloc() also nicht sicher, dass die Pointer NULL sind. Abhilfe: Entweder nach dem malloc initialisieren (siehe oben) oder calloc() benutzen. [...]
Wenn man mit calloc oder memset initalisiert und NULL haben will, dann ist diese Methode nicht portabel, oder?
Siehe oben - ich habe noch kein Unix erlebt, bei dem das schiefgeht, Ich würde David's damalige Aussage bez. der Definition von NULL nicht unterschreiben, kann sie aber mangels Zugriff auf die 'C/C++'-Standards weder widerlegen noch bestätigen.
Hehe, ich hab den Thread wiedergefunden: http://groups.google.com/groups?hl=de&lr=&ie=UTF-8&frame=right &th=e349bcf8d4eba583&seekm=874rsyxbgo.fsf%40deneb.enyo.de#s und ff. (eine Zeile, wie ueblich ;) -dnh -- 142: Microsofties ferngesteuerte Marketingdroiden, die immer nur "München" und "Amerika" murmeln können, wenns kompliziert wird. (Martin Schmitt)
participants (8)
-
Andre Heine
-
David Haller
-
Erik Herold
-
Jan.Trippler@t-online.de
-
Ralf Corsepius
-
Sebastian Huber
-
Terje Fåberg
-
Udo Neist