Array dynamisch vergrößern
-
Hallo an alle
Ich hab eine Frage. Ich lese eine Datei ein und schreibe die Zeichen in einen Buffer. Zuerst lese ich immer die Länge des kommenden Blockes ein (Hex Datei). Nun will ich das Buffer Array um diese Länge vergrößern. Danach werden die Datenbytes in den Buffer geschrieben.
Nun lese ich den nächsten Block mit der Länge und will das Array wieder vergrößern.
Kann ich das in C machen???
Danke im Voraus
Gruß Razer
-
Du legst das Array per malloc()/calloc() an und kannst anschließend mit realloc() die Größe anpassen, wenn du es brauchst.
(PS: Auch wenn C sich irgendwo notiert, wie groß der Speicherblock ist, solltest du es trotzdem mitschreiben - es gibt nämlich keinen portablen Weg, an diese Information ranzukommen)
-
Danke.
Jetzt hab ich das ins Prgramm eingebaut. Jedoch funktionieren tut es noch nicht richtig
Ich wll 10 Zeilen aus der Hex File auslesen. Der Pfad der Hex wird als Kommandozeilenparameter übergeben. Mit calloc() erschaffe ich Platz für eine Integer Variable. Dann lese ich die Anzahl der Datenbytes aus dem Hex File aus (Das funktioniert) und vergrößere den Speicher um die Anzahl der ausgelesenen Bytes. Das ganze geht 3 mal gut. Beim 4. Mal hängt sich das Prgramm auf.
Warum ist das so??? Hab leider keinen Plan
Hier der Source Code.
int main(int argc, char **argv) { FILE *hexfile; int size = 0; int i, j; int* decData = NULL, *backup; int addrDec, crc, recordTyp; int bufferlaenge = 0; unsigned char buffer[10] = {0}; decData = (int *)calloc(1, sizeof(int)); if(decData == NULL) { printf("\nCalloc() failed!"); exit(1); } backup = decData; bufferlaenge++; hexfile = fopen(argv[1], "r"); if(hexfile != NULL) { for(j = 0; j < 10; j++) { size = getDataSize(hexfile); if(size != -1) { printf("\n%d, %d\n", size, bufferlaenge); decData = (int *) realloc(decData, (bufferlaenge * sizeof(int)) + (size * sizeof(int))); if(decData == NULL) { printf("\nRealloc() failled!"); decData = backup; } bufferlaenge += size; getFromFile(hexfile, &buffer[0], 4); addrDec = hex2dec(buffer, 4); getFromFile(hexfile, &buffer[0], 2); recordTyp = hex2dec(buffer, 2); for(i = 0; i < size; i++) { getFromFile(hexfile, &buffer[0], 2); decData[bufferlaenge + i] = hex2dec(buffer, 2); } getFromFile(hexfile, &buffer[0], 2); crc = hex2dec(buffer, 2); getc(hexfile); printf("\n%d %d %d %d", size, addrDec, recordTyp, crc); } } } }
Danke im Voraus
Gruß Razer
-
Du solltest mal bufferlaenge am Ende der äusseren Schleife hochzählen.
bufferlaenge += size;
Momentan machst du das vor
for(i = 0; i < size; i++) { getFromFile(hexfile, &buffer[0], 2); decData[bufferlaenge + i] = hex2dec(buffer, 2); }
was beim Zugriff auf decData zu Problemen führt. Und logisch wohl auch nicht richtig ist. Aber das kannst du sicherlich besser beurteilen, da ich den Code nur kurz überflogen habe.
-
Hallo Groovemaster
Danke für den Tipp. Das wars. Es ist eigentlich eh logisch. Wenn ich bufferlaenge zuvor erhöhe greife ich nachher auf einen nicht freigegebenen Speicher zu und schieße beim Array raus...
So jetzt will ich das ganze in eine Funktion packen...
Nur klappt das nicht ganz so :(. Ich denke der Fehler liegt wieder irgendwo an *decData... So einen Pointer hab ich noch nie übergeben...
Ich hoffe es kann mir wer helfen.
Der Source nochmal:
void readLine(FILE *hexfile, int* size, int* addrDec, int *recordTyp, int* decData, int* backup, int* crc, int* bufferlaenge) { unsigned char buffer[5], i; *size = getDataSize(hexfile); if(*size != -1) { printf("\n%d, %d\n", *size, *bufferlaenge); decData = (int*)realloc(decData,*bufferlaenge * sizeof(int)) + (*size * sizeof(int)); if(decData == NULL) { printf("\nRealloc() failled!"); decData = backup; } getFromFile(hexfile, &buffer[0], 4); *addrDec = hex2dec(buffer, 4); getFromFile(hexfile, &buffer[0], 2); *recordTyp = hex2dec(buffer, 2); for(i = 0; i < *size; i++) { getFromFile(hexfile, &buffer[0], 2); decData[*bufferlaenge + i] = hex2dec(buffer, 2); } getFromFile(hexfile, &buffer[0], 2); *crc = hex2dec(buffer, 2); getc(hexfile); (*bufferlaenge) = (*bufferlaenge) + (*size); printf("\n%d %d %d %d", *size, *addrDec, *recordTyp, *crc); } }
Ich rufe dann das ganze so in der Main auf:
readLine(hexfile, &size, &addrDec, &recordTyp, decData, backup, &crc, &bufferlaenge);
Wo liegt denn hier der Fehler?
Danke im Voraus
Gruß Razer
-
Erstmal
Nur klappt das nicht ganz so
ist nicht sonderlich hilfreich. Da solltest du schon genauere Angaben machen.
Das einzige, was mir spontan auffällt, ist, dass i vom Typ unsigned char ist. Warum nicht int, so wie vorher? unsigned char hat ja sehr wahrscheinlich einen kleineren Wertebereich. Evtl. reicht dieser nicht aus.
Dann solltest du unbedingt deine Funktionsparameter reduzieren. Es reicht sicherlich aus, wenn du einige Variablen nur funktionslokal anlegst.
Deine realloc Strategie ist auch nicht logisch korrekt.
Normalerweise sieht das eher wie folgt aus:int* tmp = realloc(decData,*bufferlaenge * sizeof(int)) + (*size * sizeof(int)); if(tmp == NULL) { printf("\nRealloc() failled!"); } else { decData = tmp; }
Und versuche den Code einfach zu halten, zB hier
(*bufferlaenge) = (*bufferlaenge) + (*size);
Wozu die ganzen Klammern? Keine davon ist notwendig.
-
Hi
Ich hab mal ein bisschen aufgeräumt
Die Stratgie bei realloc verstehe ich jedoch nicht genau. Ich sichere zuerst den Wert wohin der Zeiger zeigt. Dann führe ich realloc() aus und wenn das fehl schlägt, setze ich den Zeifer zurück.
Den einzigen Fehler den ich gefunden habe, war bei realoc() die Klammern aber das hat auch nicht geholfen.
Derzeit passiert folgendes: Beim Ausführen macht er einmal realloc() und dann beim 2. Aufruf der Funktion brcht das Programm bei realloc() ab, bzw es kommt die Fehlermeldung von Windows das geschlossen wurde. Size und Bufferlänge werden vorher noch korrekt ausgegeben...
Hier der aktuelle Source:
void readLine(FILE* hexfile, int* addrDec, int* decData, int* bufferlaenge) { unsigned char buffer[5]; int size; int crc; int *backup; int recordTyp; int i; backup = decData; size = getDataSize(hexfile); if(size != -1) { printf("\n%d, %d\n", size, *bufferlaenge); decData = (int*) realloc(decData, *bufferlaenge * sizeof(int) + (size * sizeof(int))); if(decData == NULL) { printf("\nRealloc() failled!"); decData = backup; } getFromFile(hexfile, &buffer[0], 4); *addrDec = hex2dec(buffer, 4); getFromFile(hexfile, &buffer[0], 2); recordTyp = hex2dec(buffer, 2); for(i = 0; i < size; i++) { getFromFile(hexfile, &buffer[0], 2); decData[*bufferlaenge + i] = hex2dec(buffer, 2); } getFromFile(hexfile, &buffer[0], 2); crc = hex2dec(buffer, 2); getc(hexfile); *bufferlaenge = *bufferlaenge + size; printf("\n%d %d %d %d", size, *addrDec, recordTyp, crc); } }
Aufruf:
readLine(hexfile, &addrDec, decData, &bufferlaenge);
Ich hoffe es kann wer helfen.
Danke im Voraus
Gruß Razer
-
Razer_6 schrieb:
Die Stratgie bei realloc verstehe ich jedoch nicht genau. Ich sichere zuerst den Wert wohin der Zeiger zeigt. Dann führe ich realloc() aus und wenn das fehl schlägt, setze ich den Zeifer zurück.
Ja, in deiner separierten Funktion scheint es korrekt zu sein. Ich bezog mich da auf den originalen Code, wo nur ein Backup vor der äusseren Schleife gemacht wird, was je wenig bringt, da in der Schleife immer wieder realloc aufgerufen wird, und sich decData somit immer wieder verändern kann.
Razer_6 schrieb:
Derzeit passiert folgendes: Beim Ausführen macht er einmal realloc() und dann beim 2. Aufruf der Funktion brcht das Programm bei realloc() ab, bzw es kommt die Fehlermeldung von Windows das geschlossen wurde. Size und Bufferlänge werden vorher noch korrekt ausgegeben...
Das liegt sehr wahrscheinlich daran, dass von decData ja lediglich eine Kopie übergeben wird. Und nur diese Kopie wird innerhalb der Funktion verändert. Dh, das decData Original behält seinen Wert und übergibt beim nächsten Aufruf eine Adresse, die schon nicht mehr aktuell ist. Und damit kann realloc natürlich nichts anfangen. Die Lösung ist, du übergibst einen Zeiger auf int*, also int** decData. Beim Aufruf der Funktion muss dann natürlich die Adresse von decData übergeben werden, so wie du das schon bei addrDec machst. Innerhalb der Funktion muss decData dann dereferenziert, ebenfalls wie bei addrDec.
*decData = ... if(*decData == NULL) { printf("\nRealloc() failled!"); *decData = backup; } //...
-
Danke für den Tipp!
void readLine(FILE* hexfile, int* addrDec, int** decData, int* bufferlaenge) { backup = *decData; size = getDataSize(hexfile); if(size != -1) { printf("\n%d, %d\n", size, *bufferlaenge); *decData = (int*) realloc(*decData, *bufferlaenge * sizeof(int) + (size * sizeof(int))); if(*decData == NULL) { printf("\nRealloc() failled!"); *decData = backup; } }
Da hängt sich das Programm auf
Das mit dem Zeiger auf einen Zeiger verstehe ich so halbwegs, aber bei der Übergabe des Zeigers an Realloc steige ich aus
Wie gehört das nun???
Danke im Voraus
Gruß Razer
-
Razer_6 schrieb:
Danke für den Tipp!
Da hängt sich das Programm auf
Das mit dem Zeiger auf einen Zeiger verstehe ich so halbwegs, aber bei der Übergabe des Zeigers an Realloc steige ich aus
Wie gehört das nun???
Danke im Voraus
Gruß Razer
Realloc arbeitet, wenn
1. der Speicher bereits durch malloc alloziert wurde
2. oder von realloc verändert wurde
3. wenn der Zeiger auf NULL zeigt, dann verhält sich realloc wie mallocWenn du malloc nicht vorher aufrufst und wenn *decData != NULL, dann wird realloc abstürzen.
-
Hallo Supertrux
Ich rufe calloc() in der man auf ;)*
decData = (int *)calloc(1, sizeof(int)); if(decData == NULL) { printf("\nCalloc() failed!"); exit(1); }
Gruß Razer
-
Razer_6 schrieb:
Das mit dem Zeiger auf einen Zeiger verstehe ich so halbwegs, aber bei der Übergabe des Zeigers an Realloc steige ich aus
So wie du es dastehen hast, sieht es jedenfalls richtig aus. Daher bin ich, ohne den kompletten Code zu kennen, auch überfragt. Lässt sich denn der Absturz reproduzieren? Wenn ja, dann versuche mal mit dem Debugger die genaue Stelle herauszufinden. Zusätzlich kannst du ebenfalls mit dem Debugger Schritt für Schritt den Code prüfen, ob deine Programmlogik das tut, was sie tun soll.
-
Hallo an alle
SO ich hab mal ein bisschen gedebuggt. Hier mal die ganze Funktion mit allen relavanten Zugriffen...
void readLine(FILE* hexfile, int* addrDec, int** decData, int* bufferlaenge) { backup = *decData; size = getDataSize(hexfile); if(size != -1) { printf("\n%d, %d\n", size, *bufferlaenge); *decData = (int*) realloc(*decData, *bufferlaenge * sizeof(int) + (size * sizeof(int))); if(*decData == NULL) { printf("\nRealloc() failled!"); *decData = backup; } for(i = 0; i < size; i++) { getFromFile(hexfile, &buffer[0], 2); *decData[*bufferlaenge + i] = hex2dec(buffer, 2); } *bufferlaenge = *bufferlaenge + size; } }
Der Fehler tritt nicht bei realloc() auf, sondern beim Zugriff auf den Datenpuffer:
*decData[*bufferlaenge + i] = hex2dec(buffer, 2);
Was ist da Falsch??
Ich hoffe es kann mir jemand helfen...
Danke im Voraus
Gruß Razer
-
Fehler gefunden.
Der Zugriff muss lauten
(*decData)[*bufferlaenge + i] = hex2dec(buffer, 2);
mfg Razer