Array dynamisch vergrößern



  • 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 malloc

    Wenn 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


Anmelden zum Antworten