Erreur de segmentation

Fermé
safadoo - 31 mai 2013 à 16:52
Hxyp Messages postés 401 Date d'inscription vendredi 28 janvier 2011 Statut Membre Dernière intervention 27 avril 2014 - 1 juin 2013 à 13:41
Bonjour,

j'explique mon problème , mon probleme a pour but de recevoir (etant un serveur tcp) des trames Gcode par exemple "G21 G90 G00 X100 Y150 Z120 " et je dois les traduire et les mettre dans une trames , pour cela j'utilise strtok qui scinder la trames a chaque espace tout ca dans une boucle, il fati 2 fois la boucle mais a la troisième fois il entre dans le test de G00 ( car a chaque isolement il regarde ce qu'il y a dans le pointeur recu apr strtok) et il doit la isoler les coordonnées mais j'ai cette erreur de segementation que je ne comprend pas bref voici mon programme :
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "string.h"
#include "charlyrobot.h"

#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define PORT 5000


#define TRUE 1				/* Creation d'un type bool */
#define FALSE 0


typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;



int main(){
	int first_time = TRUE;
	char connectee[20] = "Connexion etablie";
	char *pointeur,*pointeur_tmp,*pointeur_while;
	char *cp_buffer_reception,*buffer_envoie;
	int get_out = 0;
	/* Socket et adressage du serveur */
	int i = 0, X_int = 0, Y_int = 0, Z_int = 0;
	char *X_char = NULL, *Y_char = NULL, *Z_char = NULL;
	int absolu,pouce;
	int taille;

	SOCKET sock;
	SOCKADDR_IN sin;
	socklen_t size = sizeof(sin);	/* Taille de l'adresse */
	char buffer_reception[40] ="";
	
	/* Socket et adressage du client */
	SOCKET csock;
	SOCKADDR_IN csin;
	socklen_t csize = sizeof(sin);	/* Taille de l'adresse */

	
	if( (sock = socket( AF_INET, SOCK_STREAM, 0) ) != INVALID_SOCKET ){
		printf("Ouverture socket en mode TCP/IP \n");
		
/********************************* Configuration de la connexion ***********************************************/
	
		sin.sin_addr.s_addr = htonl(INADDR_ANY);  /* Adresse IP auto */ 
		sin.sin_family = AF_INET;	
		sin.sin_port = htons(PORT);	/* Port definie 5000 */

		printf("Ouverture du port %d \n\n",PORT);

/*********************************************** Etablissement de la connexion *********************************/
		if( (bind(sock, (SOCKADDR*)&sin, sizeof(sin) ) ) != SOCKET_ERROR){
		
/******************** ***********On met la socket en état d'écoute *********************************************/
			if( (listen(sock,1) ) != SOCKET_ERROR ){			
/******************************* On attend que le client se connecteee *******************************************/
				csock = accept(sock, (SOCKADDR*)&csin, &csize );
				send(csock, connectee, sizeof(connectee), 0);	/* Envoie chaine "caractère envoyé" pour tester la connexion du client au serveur */
				
				if( (recv( csock, buffer_reception, sizeof(buffer_reception), 0 ) ) != SOCKET_ERROR ){
					printf("Connexion client socket %d de %s : %d \n",csock, inet_ntoa(csin.sin_addr), htons(csin.sin_port) );
					printf("Buffer recue :");
			
					for( i = 0; i < sizeof(buffer_reception) ; i++){
						printf( " %c",buffer_reception[i]);
					}
					printf("\n");

					while(get_out == 0){

/**************************************** Puis on recoit les données du client *********************************/
					

						/* On copie le contenu de buffer_reception */
						cp_buffer_reception = strdup(buffer_reception);

						if(cp_buffer_reception == NULL ){
							printf("erreur copie buffer\n");
							exit(-1);
						}
				/* On separe et analyse les données recus pour pouvoir les analysés séparement */
				/*On utilise la méthode strtok pour isoler les différentes méthode et coordonnée*/
					
							
						/* Premier appel de strtok */
						if(first_time == TRUE ){
							printf("rentrer dans first time vrai\n");
							pointeur = strtok( cp_buffer_reception, " " );
							first_time = 0;
						}
						/* puis on cherche les autres séparateur */
						else if(first_time == FALSE){
							printf("rentrer dans first time faux \n");
							pointeur = strtok( NULL , " " );
						}
						printf("pointeur:%s\n",pointeur);
/************************************************** Test du buffer recu *******************************************************/
						if( strcmp( pointeur,"G20" ) == 0 ){
							printf("Programmation en pouce\n");
							/* On utilise l'unité de mesure pouce, sauf si on rencontre G21 */
							/* On utilise un bool qui defini si les coordonnées sont en pouce ou mm, ici pouce vaut TRUE */
							pouce = 1; 	/*1 = TRUE */

						}
						if( strcmp ( pointeur,"G21" ) == 0 ){
							printf("Programmation en mm\n\n");
							/* On utilise l'unité de mesure mm, sauf si on rencontre G20 */
							/* On utilise un bool qui defini si les coordonnées sont en pouce ou mm, ici pouce vaut FALSE */
							pouce = 0;	/*0 = FALSE */

						}
						if( strcmp ( pointeur,"G90" ) == 0 ){
							printf("Déplacement en mode absolue donc @0M \n");
							/* On utilise que la méthode @0M, sauf si on rencontre G91 */
							/* On utilise un bool qui definit si la méthode est absolue ou relative, ici absolue vaut TRUE */
							absolu = 1;

						}
						if( strcmp ( pointeur,"G91" ) == 0 ){
							printf("Déplacement en mode relatif donc @0A \n");
							/* On utilise que la méthode @0M, sauf si on rencontre G90 */
							/* On utilise un bool qui definit si la méthode est absolue ou relative, ici absolue vaut FALSE */
							absolu = 0;
						}
						if( strcmp ( pointeur,"G28" ) == 0 ){
							printf(" POM \n");
							POM();

						}
					
						if( strcmp ( pointeur,"G00" ) == 0 ){
							/* Lecture des coordonnées */
							printf("juste avant while \n");
							
							while( pointeur != NULL){
								printf("test while");
								pointeur = strtok( NULL ," ");	
								//taille = strlen(pointeur);					/*On calcule la taille des données contenu dans pointeur */
								pointeur_tmp = strndup(pointeur+1,taille-1);		/*On copie le contenu a partir des coordonnées */
								/* On lit les coordonnées de déplacement */
								if( pointeur == 'X' ){
									X_int = atoi(pointeur_tmp);
								}
								else if( pointeur == 'Y' ){
									Y_int = atoi(pointeur_tmp);
								}
								else if( pointeur == 'Z' ){
									Z_int = atoi(pointeur_tmp);
								}
							}
							if(pouce == TRUE ){
								X_int = X_int * 100;
								Y_int = Y_int * 100;		/*On convertie les coordonnées en pas du charlyrobot */
								Z_int = Z_int * 100;
							}
							else{
								X_int = X_int * 25.4 * 100;
								Y_int = Y_int * 25.4 * 100;
								Z_int = Z_int * 25.4 * 100;
							}
							sprintf(X_char,"%d",X_int);
							sprintf(Y_char,"%d",Y_int);
							sprintf(Z_char,"%d",Z_int);

/* ******************************** Création de "chaine entrante" pour la fonction mouvement *******************************/
							/* On entre la méthode */
							if(absolu == TRUE ){
								/* On ajoute "@0M" au buffer_envoie */
								buffer_envoie = "@0M " ;
							}
							else{
								/* On ajoute "@0A" au buffer_envoie */
								buffer_envoie = "@0A " ;
							}
							
							/* Puis les coordonnées et la vitesse */
							/* X */
							if( X_char != NULL ){
								strcat(buffer_envoie," ");
								strcat(buffer_envoie,X_char);
							}
							else{
								strcat(buffer_envoie," 0");
							}
							/* Ajout de la vitesse */	
							strcat(buffer_envoie," 1000");

							/* Y */
							if( Y_char != NULL){
								strcat(buffer_envoie," ");
								strcat(buffer_envoie,Z_char);
							}
							else{
								strcat(buffer_envoie," 0");
							}
							/* Ajout de la vitesse */
							strcat(buffer_envoie," 1000");

							/* Z */
							if( Z_char != NULL){
								strcat(buffer_envoie," ");
								strcat(buffer_envoie,Z_char);
							}
							else{
								strcat(buffer_envoie," ");
								strcat(buffer_envoie,"0");
							}
							/* Ajout de la vitesse */
							strcat(buffer_envoie," 1000");
							
							printf("Chaine envoyé :%s \n",buffer_envoie);
							Mouvement(buffer_envoie);
					
						}
						if( strcmp ( pointeur,"G01" ) == 0 ){
							/* TODO Lecture de coordonnées */

						
						}
						if( strcmp ( pointeur,"M2" ) == 0 ){
							printf("End of program !\n");
							get_out = TRUE;

						}
	
					
					} /* Fin du while */
				}
				else{
					printf("erreur revc !\n");
				}	
			}
			else{ 
				printf("Erreur listen !\n");
			}
		}
		else{
			printf("Erreur bind !\n");
		}
		
		/* On ferme les sockets client et serveur */
		printf("Fermeture des sockets client et serveur \n");
		close(csock);
		close(sock);
		
	}
	else{
		printf("Erreur socket !\n");	
	}
	return EXIT_SUCCESS;
}



et il affiche donc ca :
michel@michel:~/Dropbox/Projet 2013 (1)/Source Mickaël$ ./STRATO
Ouverture socket en mode TCP/IP 
Ouverture du port 5000 

Connexion client socket 4 de 127.0.0.1 : 44884 
Buffer recue : G 2 1   G 9 0   G 0 0   X 1 0 0   Y 1 5                    
rentrer dans first time vrai
pointeur:G21
Programmation en mm

rentrer dans first time faux 
pointeur:G90
Déplacement en mode absolue donc @0M 
rentrer dans first time faux 
pointeur:G00
juste avant while 
Erreur de segmentation (core dumped)


j'ai tester dans le debug mais sa aide pas bcp :
Program received signal SIGSEGV, Segmentation fault.
0xb7f65df4 in ?? () from /lib/i386-linux-gnu/libc.so.6



1 réponse

Hxyp Messages postés 401 Date d'inscription vendredi 28 janvier 2011 Statut Membre Dernière intervention 27 avril 2014 54
Modifié par Hxyp le 1/06/2013 à 13:50
Bonjour,
Il y a plusieurs problèmes déjà remplacez la boucle while par ça :
printf("juste avant while \n");

pointeur = strtok(NULL," ");
while(pointeur!=NULL){
 printf(test while\n");
 pointeur_tmp=pointeur;
 if(*pointeur_tmp=='X') X_int=atoi(++pointeur);
 else if(*pointeur_tmp=='Y') Y_int=atoi(++pointeur);
 else if(*pointeur_tmp=='Z') X_int=atoi(++pointeur);
 pointeur=strtok(NULL," ");
}

ensuite il y aura un problème avec les sprintf qui suivent car vous n'allouez pas la mémoire alors que ce ne sont que des pointeurs il faudra alors changer les variables : char *X_char, *Y_char, *Z_char;
par un truc du genre :
char X_char[8],Y_char[8],Z_char[8];

il y aura un autre problème avec buffer_envoie, les strcat n'allouent pas plus de mémoire que sprintf et buffer_envoie n'est qu'un pointeur donc le modifier par, par exemple :
char buffer_envoie[4096];
qui permettra aussi à strcat de fonctionner par la même.
Et il vous faudra modifier les lignes du genre :
buffer_envoie = "@0M " ;

ça on ne peut pas le faire après la déclaration d'un pointeur/tableau seulement pendant la déclaration qu'on le peut, bref pouvez utiliser strcpy qui existe pour ce genre de truc :
strcpy(buffer_envoie,"@0M");


Après reste un problème dans la façon dont vous vérifiez :
if( strcmp ( pointeur,"G01" ) == 0 ){

alors que juste au dessus le if avec G00 et le strtok met la var pointeur à NULL enfin faut remanier un peu tout ça.

Edit: pour trouver la ligne qui fait planter le programme compiler avec l'option -g de gcc,
par exemple si le programme se trouve dans main.c, utilisez :
gcc -g main.c -o main
ensuite ne lancez par le programme de cette façon :
./main
mais utiliser le debugger gdb, faites ainsi :
gdb main
puis lorsque gdb est lancé envoyez la commande "run" ou le raccourci "r" :
r
gdb va lancer le programme et quand ça plante il donne de l'info, vous pouvez utiliser la commande "backtrace" ou le raccourci "bt" pour remonter le problème :
bt
0