Segmentation Fault



  • Hi,

    wenn ich das unten stehende Programm ausführe, bekomme ich, sobald im SendingThread die Zeile fgets(..) in der Schleife ausgeführt wird einen Segmentation Fault.
    Wenn ich die Eingabe hart in den Puffer schreibe löst die Zeile read in der Schleife einen Segmentation Fault aus.

    Wodran kann dies liegen? Die Puffer werden doch vorher erfolgreich verwendet?

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <pthread.h>
    #include <errno.h>
    #include <semaphore.h>
    #define BUFFERSIZE 1024
    
    sem_t sem;
    
    static void* listeningThread(void *arg) {
    	int sock, concrsock;
    	struct sockaddr_in addr;
    	char* rSendingBuffer = malloc(BUFFERSIZE);
    	char* rReceiveBuffer = malloc(BUFFERSIZE);
    	const int y = 1;
    	int retval;
    	socklen_t addrlen;
    
    	printf("Start des ListeningThreads\n");
    
    	if( (sock = socket(AF_INET, SOCK_STREAM, 0)) > 0) {
    		printf("Socket zum Empfangen erfolgreich angelegt\n");
    		fprintf(stderr, "%s\n", strerror(errno));
    		//printf("%d\n",sock1);
    	}
    
    	if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(int)) != 0) {
    		printf("setsockopt schlug fehl\n");
    		fprintf(stderr, "%s\n", strerror(errno));
    	}
    
    	addr.sin_family = AF_INET;
    	addr.sin_port = htons(17000);
    	addr.sin_addr.s_addr = INADDR_ANY;
    
    	if(bind(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
    		printf("Port kann nicht belegt werden\n");
    		fprintf(stderr, "%s\n", strerror(errno));
    	}
    
    	if( (listen(sock, 10)) != 0) {
    		printf("Listen nicht erfolgreich\n");
    		fprintf(stderr, "%s\n", strerror(errno));
    	}
    	addrlen = sizeof(struct sockaddr_in);
    	printf("ist am warten....\n");
    	sem_post(&sem);
    	while(1) {
    
    		concrsock = accept(sock, (struct sockaddr*)&addr, &addrlen);
    		if( concrsock > 0) {
    			printf("Es ist ein Klient (%s) verbunden...\n", inet_ntoa(addr.sin_addr));
    		}
    
    		/* Erstmaliger Kontakt - mit Alive antworten */
    		rSendingBuffer = "Alive\0";
    		retval = send(concrsock, rSendingBuffer, strlen(rSendingBuffer), 0);
    		printf("Erfolgreich Alive msg mit %d Bytes gesendet\n", retval);
    		/*fprintf(stderr, "%s\n", strerror(errno));*/
    
    		/* Evtl Vereinbarungen treffen */
    		retval = recv(concrsock, rReceiveBuffer, BUFFERSIZE-1, 0);
    		printf("Erfolgreich Vereinbarungen mit %d Bytes empfangen\n", retval);
    		//fprintf(stderr, "%s\n", strerror(errno));
    		//printf("%s\n", rReceiveBuffer);
    
    		/*Ack schicken */		
    		rSendingBuffer = "ack\0";
    		retval = send(concrsock, rSendingBuffer, strlen(rSendingBuffer), 0);
    		printf("Erfolgeich das ack mit %d Bytes gesendet\n", retval);
    
    		rReceiveBuffer = '';
    
    		/* Datenübertragung beginnen */
    
    		do {
    			printf("Es wird auf Nachricht gewartet\n");
    			retval = recv(concrsock, rReceiveBuffer, BUFFERSIZE-1, 0);
    			if(retval > 0) {
    				rReceiveBuffer[BUFFERSIZE] = '\0';
    			}
    			printf("In der Hauptuebertragung Nachricht %s erhalten\n", rReceiveBuffer);
    
    		} while(strcmp(rReceiveBuffer, "complete"));
    		//} while(0);
    
    		close(concrsock);
    
    	}
    
    	printf("Listening zu Ende");
    
    }
    
    static void* sendingThread(void* arg) {
    	sem_wait(&sem);
    	sem_post(&sem);
    	int sendingSocket;
    	char* sSendingBuffer = malloc(BUFFERSIZE);
    	char* sReceivingBuffer = malloc(BUFFERSIZE);
    	struct sockaddr_in address;
    	char* adr = "192.168.1.101";
    	char temp[255];
    	int retval;
    	char* tempBuffer;
    
    	printf("Start des Sending Threads\n");
    
    	if( (sendingSocket = socket(AF_INET, SOCK_STREAM,0)) > 0) {
    		printf("Socket zum Senden erfolgreich angelegt\n");
    	}
    
    	address.sin_family = AF_INET;
    	address.sin_port = htons(17000);
    	inet_aton(adr, &address.sin_addr);
    
    	printf("Verbinden?\n");
    	fgets(temp, 254, stdin);
    	if(connect(sendingSocket, (struct sockaddr*)&address, sizeof(address)) == 0) {
    		printf("Erfolgreich verbunden\n");
    	}
    
    	/* Alive erhalten */
    	retval = recv(sendingSocket, sReceivingBuffer, BUFFERSIZE-1, 0);
    	printf("Erfolgreich Alive mit %d Bytes empfangen\n",retval);
    	//printf("%s\n", sReceivingBuffer);
    
    	/* evtl Vereinbarungen schicken */
    	sSendingBuffer = "keine\0";
    	retval = send(sendingSocket, sSendingBuffer, strlen(sSendingBuffer), 0);
    	printf("Erolgreich Vereinbarungen mit %d Bytes gesendet\n",retval);
    
    	/* Ack erhalten */
    	retval = recv(sendingSocket, sReceivingBuffer, BUFFERSIZE-1, 0);
    	printf("Erfolgreich ack mit %d Bytes empfangen\n",retval);
    	//printf("%s\n", sReceivingBuffer);
    
    	/* Übertragung beginnen , bei Entwicklung noch per fgets, später dann vermutl. txt dateien... */
    
    	do {
    		//tempBuffer = malloc(BUFFERSIZE);
    		printf("Nachricht zum Verschicken: ");
    		printf("im SendingBuffer: %s\n", sSendingBuffer);
    		//fgets(sSendingBuffer, BUFFERSIZE-1, stdin);
    		//printf("Ich schicke jetzt %s in der Hauptuebertragung", tempBuffer);
    		//fprintf(stderr, "%s\n", strerror(errno));
    		//printf("Im Buffer steht: %s\n", tempBuffer);
    		send(sendingSocket, sSendingBuffer, strlen(sSendingBuffer), 0);
    		retval = recv(sendingSocket, sReceivingBuffer, BUFFERSIZE-1, 0);
    		printf("Nachricht erhalten: %s\n", sReceivingBuffer); 
    	} while(strcmp(sSendingBuffer, "fertig\n"));
    	//} while(0);
    
    }
    
    int main(void) {
    
    	pthread_t listeningID;
    	pthread_t sendingID;
    	char* dummy;
    	int** ret, ret2;
    	dummy = "Achja, du schon wieder\0";
    	sem_init(&sem, 0, 1);
    
    	sem_wait(&sem);
    	pthread_create(&listeningID, NULL, listeningThread, (void*)dummy);
    	pthread_create(&sendingID, NULL, sendingThread, (void*)dummy);
    	pthread_join(listeningID, (void**)ret);
    	pthread_join(sendingID, (void**)ret2);
    
    	exit(EXIT_SUCCESS);
    }
    

    vielen dank.

    mfg naja



  • verwende selber einen Debugger oder valgrind (am besten mit -g kompilieren, dann ziegt Valgrind sogar den fehlerhaften Code an).

    Keiner wird sich die Mühe machen, in so einem langen Code nach den Fehlern zu suchen.

    Mir ist aber dennoch aufgefallen:

    char* sSendingBuffer = malloc(BUFFERSIZE);
    ...
    sSendingBuffer = "keine\0";
    

    es sollte 1. BUFFERSIZE+1 heißen, damit \0 gespeichert werden kann (sofern man mit Strings arbeitet).

    Bei sSendingBuffer = "keine\0"; kopierst du nicht den Inhalt "keine" in sSendingBuffer sondern überschreibst du den Wert, worauf der Zeiger zeigt, womit sSendingBuffer auf read-only memory zeigt. Wenn du fgets drauf laufen lässt, dann kracht es eben. Verwender man: memcopy(3).

    Außerdem "keine\0" und "keine" (und "keine\0 und alles andere was hinter dem slash-0 kommt" ) sind inhaltsmäßig äquivalent, bei String-Literalen brauchst du nicht selber die \0-Marke zu setzen.



  • Hi,

    danke der Tip mit dem Read-Only-Memory hat mein Problem gelöst.

    nutze nun strcpy.

    mfg naja


Anmelden zum Antworten