Wo liegt hier der Fehler: Funktion ersetzte String im String-Buffer



  • Hallo, ich hab mir eine kleine Funktion geschrieben um einen String beliebiger Länge in einem Char-Buffer gegen einen anderen String beliebiger Länge auszutauschen.
    Leider schein da etwas mit dem malloc in der Funktion testfunction nicht zu stimmen, wenn ich den Speicher mit dem Wert allociere den ich rechnerisch für den Buffer brauche crasht das Programm, nehme ich jedoch einen Wert der weit über dem benötigten Speicherbedarf liegt klappt es. Es handelt sich dabei um die Zeilen:

    real_lenght = buffersize + anzahl*(strlen(string2) - strlen(string1)) + 1;	//benötigte Länge + 1
    //		new_buffersize = real_lenght + 1;					//so geht's nicht
    		new_buffersize = buffersize + 10*anzahl*strlen(string2) + 1;		//ich weiss net warum, aber so geht's
    

    Ich poste hier mal meinen kompletten Sourcecode, d.h. wer möchte kann das Ganze kompilieren so wie es ist und sich den Fehler anschauen.
    Möglicherweise mache ich auch irgendwo einen Fehler beim Berechnen des benötigten Speichers, oder die Funktionen memset, memcpy und memmove lassen sich so nicht ausführen.
    Aber wie bereits gesagt, wenn der Wert von malloc recht groß ist, dann gehts blickt da jemand durch und kann mir helfen, dank schon mal vorab.

    #include <stdio.h>
    #include <io.h>
    #include <stdlib.h>
    #include <string.h>
    #include <direct.h>
    #include <winsock.h>
    #include <malloc.h>
    
    //ermittelt die Größe einer Datei
    u_long File_GetFileSize(char *filename){
    
    	struct _finddata_t		hFile;
    	long			fHandle;
    	u_long			file_size;		
    
    	fHandle = _findfirst(filename, &hFile);
    	if(fHandle == -1){
    		return 0;
    	}else{
    		file_size = hFile.size;
    		_findclose(fHandle);
    		return file_size;
    	}
    }
    
    //läd den Inhalt einer Datei in einen Datenpuffer
    int File_LoadBinaryFile(char *filename, u_char *databuffer, int buffersize){
    
    	FILE		*datei;
    	int		len;
    
    	datei = fopen(filename,"rb");
    	if(!datei){
    		return 0;
    	}
    	len = fread(databuffer, buffersize, 1, datei);
    	fclose(datei);
    	return File_GetFileSize(filename);
    }
    
    /*
    method 0 :	der Platzbedarf wird ermittelt
    method 1 :	der String wird ausgetauscht
    */
    int String_ChangeString(u_char *buffer, u_char *oldString, u_char *newString, int len_buffer, int len_oldString, int len_newString, int method){
    
    	int			i, j, replace_counter = 0, tmp_counter;
    
    	for(i = 0; i < len_buffer; i++){
    		if(*(buffer + i) == *(oldString)){
    			if(len_oldString == 1){
    				tmp_counter = len_oldString;
    			}else{
    				tmp_counter = 1;
    				for(j = 1; j < len_oldString; j++){
    					if(*(buffer + i + j) == *(oldString + j)){
    						tmp_counter++;
    					}else{
    						break;
    					}
    				}
    			}
    			if(tmp_counter == len_oldString){
    				replace_counter++;
    				if(method == 1){
    					memmove((buffer + i), (buffer + i + len_oldString), (len_buffer - i - len_oldString));
    					memset((buffer + i + len_buffer - len_oldString), 0, len_oldString);
    					len_buffer -= len_oldString;
    					memmove((buffer + i + len_newString), (buffer + i), (len_buffer - i));
    					memcpy((buffer + i), newString, len_newString);
    					len_buffer += len_newString;
    					i += (len_newString - 1);
    				}else{
    					i += (len_oldString - 1);
    				}
    			}
    		}
    	}
    	return replace_counter;
    }
    
    void testfunction(u_char *buffer, int buffersize){
    
    	int			anzahl, new_buffersize, real_lenght;
    	u_char			*buffer2;
    	char			string1[256], string2[256];
    
    	strcpy(string1, "buffer");
    	strcpy(string2, "123 blabla");
    	anzahl = String_ChangeString(buffer, string1, string2, buffersize, strlen(string1), strlen(string2), 0);	//Anzahl der Ersetzungen ermitteln
    	printf("anzahl: %i\n", anzahl);
    	if(anzahl == 0){
    		return;
    	}
    	if(strlen(string1) < strlen(string2)){
    		real_lenght = buffersize + anzahl*(strlen(string2) - strlen(string1)) + 1;	//benötigte Länge + 1
    //		new_buffersize = real_lenght + 1;					//so geht's nicht
    		new_buffersize = buffersize + 10*anzahl*strlen(string2) + 1;		//ich weiss net warum, aber so geht's
    		printf("\nnew_buffersize: %i\n", new_buffersize);
    		buffer2 = malloc(new_buffersize);
    		if(buffer2){
    			memset(buffer2, 0, new_buffersize);
    			memcpy(buffer2, buffer, buffersize);
    			anzahl = String_ChangeString(buffer2, string1, string2, real_lenght, strlen(string1), strlen(string2), 1);
    			*(buffer2 + real_lenght) = '\0';
    			printf(buffer2);
    			printf("\nAnzahl: %i\n", anzahl);
    			free(buffer2);
    		}else{
    			printf("Error: can't malloc buffer2\n");
    		}
    	}else{
    		anzahl = String_ChangeString(buffer, string1, string2, buffersize, strlen(string1), strlen(string2), 1);
    		printf(buffer);
    		printf("\nAnzahl: %i\n", anzahl);
    	}
    }
    
    int main(int argc, char *argv[]){
    
    	int			back = 0;
    	char			filename[1024];
    	u_char			*filebuffer;
    	u_long			filesize;
    
    	strcpy(filename, "main.c");
    	filesize = File_GetFileSize(filename);
    	if(filesize != 0){
    		filebuffer = malloc(filesize);
    		if(filebuffer){
    			File_LoadBinaryFile(filename, filebuffer, filesize);
    			testfunction(filebuffer, filesize);
    			free(filebuffer);
    		}else{
    			printf("Error: can't malloc filebuffer\n");
    			back = -1;
    		}
    	}else{
    		printf("Error: file with size 0 found\n");
    		back = -1;
    	}
    	getchar();
    	return(back);
    }
    


  • Also, ich weiß nicht ganz genau, was du damit bezweckst, aber ich denke das Problem liegt in Zeile 67:

    memset((buffer + i + len_buffer - len_oldString), 0, len_oldString);
    

    Dort langst Du (nach meinem Debugging) über Deine Buffergrenze hinaus und setzt einen nicht allokierten Speicherbereich zu Null.

    Außerdem schiebst Du in Zeile 69:

    memmove((buffer + i + len_newString), (buffer + i), (len_buffer - i));
    

    wieder über das Speicherende hinaus, so wie ich das sehe.

    Insgesamt denke ich, das ist zu kompliziert. Warum schiebst Du hin und her, du musst doch bloss den hinteren Teil des Buffers um strlen(string2) - strlen(string1) verschieben und das andere überschreiben.

    Ich hoffe, ich erzähle jetzt nicht den totalen Käse, habe leider nicht besonders viel Zeit, um das anzuschauen.



  • Danke für die Antwort, du hast mich in die richtige Richtung geschubst. Mit Zeile 67 hast du recht gehabt, das hab ich echt übersehen, ich hab deinen Rat befolgt und es komplett anderst gemacht. Zeile 65 -75 sieht nun so aus:

    if(method == 1){
    		if(len_newString != len_oldString){
    			memmove((buffer + i + len_newString), (buffer + i + len_oldString), (len_buffer - i - len_oldString));
    			len_buffer += (len_newString - len_oldString);
    		}
    		memcpy((buffer + i), newString, len_newString);
    		i += (len_newString - 1);
    	}else{
    		i += (len_oldString - 1);
    	}
    

    bei ehemals Zeile 69 gebe ich dir auch recht, insofern daß der Aufruf der Funktion String_ChangeString mit der falschen Länge erfolgte

    falsch (Zeile 104):

    anzahl = String_ChangeString(buffer2, string1, string2, real_lenght, strlen(string1), strlen(string2), 1);
    

    dies sollte richtig sein (Zeile 104):

    anzahl = String_ChangeString(buffer2, string1, string2, buffersize, strlen(string1), strlen(string2), 1);
    

    ich glaube jetzt gehts, aber vieleicht findest du nochmals die Zeit drauf zu schauen.


Anmelden zum Antworten