realloc() funktioniert nicht
-
Ich schreibe ein Programm was eine Huffman-Codierung realisieren soll. Unter anderem habe ich einen binären Heap verbaut. Für den Heap möchte ich dynamisch Speicher anfordern. Der Heap ist als Struktur angelegt. Er hat unter anderem zwei Instanzen size und max_size, wobei size die tatsächliche Anzahl der Elemente des Heaps ist und max_size die Anzahl reservierter Speicherplätze für Elemente. Jedes mal wenn ein neues Element eingefügt wird, dann wird size inkrementiert. Sobald size größer als max_size ist, wird ein Memory Manager für den Heap aufgerufen um neuen Speicher zu reservieren. Diese Funktion sieht wie folgt aus:
BOOL bheap_manage_memory(void) { BTREENODE *btn_ptr; size_t d; btn_ptr = bh.root; /* * If the number of elements exceeds the memory, more memory is allocated. */ if (bh.size > bh.max_size) { printf("Memory Manager active. Expanding...\n"); bh.max_size += MEM_STEP_SIZE; printf("max_size: %u\n", bh.max_size); d = (bh.max_size) * sizeof(BTREENODE); printf("sizeof: %u\n", d); btn_ptr = realloc(btn_ptr, d); bh.root = btn_ptr; } return (bh_ptr->root == NULL) ? FALSE : TRUE; }
Zur Erläuterung:
MEM_STEP_SIZE ist gleich 5.
bh ist die globale Variable in der der Heap gespeichert ist.
Die Elemente des Heaps sind vom Typ BTREENODE.Zum Zeitpunkt wo der Memory Manager aufgerufen wird, konnten schon mehrere Operationen erfolgreich auf dem Heap ausgeführt werden. Bis zur Zeile mit realloc() wird alles sauber ausgeführt, dann gibt es folgende Ausgabe:
"1 [main] huffman 4032 sig_send: wait for sig_complete event failed, signal 6, rc 258, Win32 error 0
60019314 [main] huffman 4032 sig_send: wait for sig_complete event failed, signal -34, rc 258, Win32 error 0
120046681 [main] huffman 4032 sig_send: wait for sig_complete event failed, signal -34, rc 258, Win32 error 0
180074049 [main] huffman 4032 sig_send: wait for sig_complete event failed, signal 6, rc 258, Win32 error 0
240101408 [main] huffman 4032 sig_send: wait for sig_complete event failed, signal -34, rc 258, Win32 error 0
300127780 [main] huffman 4032 sig_send: wait for sig_complete event failed, signal -34, rc 258, Win32 error 0"Ich habe das nach ein paar Minuten abgebrochen, es wäre aber sicherlich noch weitergelaufen. Ich bin noch ziemlicher Anfänger in C und kann mit dieser Fehlermeldung überhaupt nichts anfangen. Beim Googlen habe ich auch nichts gefunden, was mir weitergeholfen hätte.
Ich code mit Netbeans, compiliere mit CYGWIN und mein Betriebssytem ist Windows 7 auf einer 32-Bit-Maschine. Für Tips jeglicher Art wäre ich dankbar.
-
1. Der Name "d" ist für eine Variable nicht sonderlich aussagekräftig.. :p
2. Du prüfst den Rückgabewert von realloc() nicht!
3. Es mag an der Uhrzeit liegen - aber der Sinn von btn_ptr entzieht sich mir irgendwie..
4. Makros finde ich irgendwie immer so unschön..
5. So - jetzt habe ich viel gemeckert und wenig geholfen, liegt aber wohl daran dass mir hier auch nichts auffällt. Solange ich also nichts übersehe sollte der Fehler an einer anderen Stelle liegen, vielleicht postest Du noch mal etwas mehr Code.Ach ja, ich hoffe Du versuchst nicht das letzte Element einzufügen bevor Du Speicher reservierst - dass hat sich oben so angehört.
-
cooky451 schrieb:
Ach ja, ich hoffe Du versuchst nicht das letzte Element einzufügen bevor Du Speicher reservierst - dass hat sich oben so angehört.
Genau den Verdacht habe ich hier auch.
Normalerweise prüfe ich immmer auf "size >= maxsize", bevor ich das element hinzufüge.
Denn wie kann die Size größer sein als der verfügbare Speicher. Das geht nicht und der Code sollte auch nicht den Eindruck vermitteln, als wäre das so.
-
cooky451 schrieb:
1. Der Name "d" ist für eine Variable nicht sonderlich aussagekräftig.. :p
Ja, stimmt. Normalerweise würde ich die größe der zu reservierenden Speicherblöcke auch direkt in realloc statt in der Zeile darüber. Ich wollte mir aber vorher angucken, ob der Wert richtig geschrieben wird und ob das vielleicht der Fehler ist.
cooky451 schrieb:
2. Du prüfst den Rückgabewert von realloc() nicht!
Doch, schau mal ganz unten. Da wird false ausgegeben, wenn realloc mit einen Null-Pointer liefert. Der Memory Manager wird immer so aufgerufen, daß das Programm beendet wird, wenn er false liefert. Es dürfte also nicht zu Segmentation Faults kommen. Im übrigen könnte ich ja erst nach dem Aufruf von realloc prüfen und ich komme ja nicht über den Aufruf hinaus.
cooky451 schrieb:
3. Es mag an der Uhrzeit liegen - aber der Sinn von btn_ptr entzieht sich mir irgendwie..
Ist ein Überbleibsel. Ich bin noch ganz neu bei Strukturen und so. Ein paar Mal hatte ich das Problem, daß ich eine Instanz einer Variable in einer bestimmten Schreibweise ansprechen wollte, was aber mit der struct->element Schreibweise nicht funktinoiert. Ein Arrayaufruf wie array[7]++; funktioniert, aber struct->array[7]++; funktionierte nicht. Wenn was nicht funktioniert, dann versuche ich auch mal verschiedene Schreibweisen oder in einer Variable zwischenspeichern.
cooky451 schrieb:
4. Makros finde ich irgendwie immer so unschön..
Ich habe doch gar keine verwendet!?
cooky451 schrieb:
5. So - jetzt habe ich viel gemeckert und wenig geholfen, liegt aber wohl daran dass mir hier auch nichts auffällt. Solange ich also nichts übersehe sollte der Fehler an einer anderen Stelle liegen, vielleicht postest Du noch mal etwas mehr Code.
Ach ja, ich hoffe Du versuchst nicht das letzte Element einzufügen bevor Du Speicher reservierst - dass hat sich oben so angehört.
Nein, ich poste mal die Funktion die den heap initialisiert und die Funktion, die den Memory Manager aufruft.
BOOL bheap_insert(BTREENODE btn) { BOOL memory_allocated; BTREENODE *last_node_ptr; bh.size++; memory_allocated = bheap_manage_memory(); /* * Will insert the new node if enough memory is available. */ if (memory_allocated) { /* Inserting first node. */ if (bh.size == 1) { *(bh.root) = btn; } else if (bh.size > 1) { last_node_ptr = bh.root + (bh.size - 1); *last_node_ptr = btn; bheap_sift_up(); } } else { bh.size--; printf("Memory error. Could not allocate memory.\n"); } return memory_allocated; }
bheap_sift_up sorgt dafür, daß die Heap-Bedingung wieder hergestellt wird.
extern BHEAP create_bheap(void) { BTREENODE *btn_ptr; btn_ptr = malloc(MEM_STEP_SIZE * sizeof(BTREENODE)); if (btn_ptr != NULL) { /* Reserve memory. */ bh.root = btn_ptr; /* Set initial size. */ bh.size = 0; bh.max_size = MEM_STEP_SIZE; bh_ptr =& bh; } else { printf("Memory allocation failed. Burn your computer.\n"); } }
Hier wird der Heap initialisiert. Der Aufruf von malloc funktioniert. Am Ende wird noch kurz ein Pointer initialisiert. Ich glaube, ich schrieb weiter oben, daß ich zwei globale Variablen habe: bh ist der heap als Variable, bh_ptr ein Pointer darauf.
Könnte es denn sein, daß das Problem gar nicht in meinem Quellcode liegt, sondern Windows 7 ein Problem damit hat Speicher an mein Programm zu vergeben?
-
DudeDudeson schrieb:
Könnte es denn sein, daß das Problem gar nicht in meinem Quellcode liegt, sondern Windows 7 ein Problem damit hat Speicher an mein Programm zu vergeben?
Ich sags mal so: Es ist recht unwahrscheinlich. (Quantenmechanik etc. ;))
Der Fehler sollte (wird(!)) woanders liegen.Am besten räumst Du den Quellcode einmal komplett auf (wozu einmal bh und dann noch ein Pointer da drauf? usw.) und postest dann alle Speicherrelevanten Teile. So ist das ehrlich gesagt teilweise etwas mühselig zu lesen
Dann sollte man den Fehler schon finden!
-
Globale Variablen sind ganz schlecht.
Übergebe deine nötigen Sachen als Parameter, in diesem Fall als Zeiger.
Die Programmstruktur ist sauberer, leichter debugbar und für Multithread-Kontexte vorbereitet.
-
Also vorgestern war an meiner Fachhochschule und habe meinen Quellcode dort getestet. Da lief er einwandfrei. Ich habe dann vor Ort aber auch noch ein bißchen was geändert. Eben wollte ich gucken, ob ich mit dem originalen Quellcode den Fehler noch mal auf meinem System zu Hause nachvollziehen kann.
Hier zu Hause kann ich den Fehler auch nicht mehr reproduzieren, obwohl ich am Code nichts geändert habe. Ich habe den alten Code verwendet, nicht die geänderten Daten aus der FH.
Ich finde es immer zwar total nervig, einen Fehler nicht verstanden zu haben, aber jetzt kann ich wenigstens weiter arbeiten.