IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Erreur de Segmentation non localisée


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2018
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2018
    Messages : 8
    Par défaut Erreur de Segmentation non localisée
    Bonjour,
    j'essaye d'écrire un code qui puisse replacer les occurrences d'un texte par un autre en utilisant les primitives système posix mais j'ai une erreur de segmentation dans mon code que je n'arrive pas à localiser (j'ai essayé gdb mais en vain) si quelqu'un arriverait à cibler l'erreur, je vous remercie.

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    #include <stdio.h> 
    #include <string.h> 
    #include <stdlib.h> 
    #include <sys/stat.h> /* open */
    #include <unistd.h> /*read*/
    #include <fcntl.h>  /* open */
    #include <stdio.h>  /* printf */
    #include <string.h> /* strerror() */
    #include <errno.h>  /* errno */
     
     
    #define READ_LEN 1024
     
    /**
     * \brief source file copied into destination file
     * \param source file name
     * \param source file destination 
     * \return 1 succes, -1 if fail
     */
     
     
    int replaceWord(char * s, char *oldW, char * newW,char *result) 
    { 
        //char result[1024]; 
        int i, cnt, longueur = 0; 
        int newWlen = strlen(newW); 
        int oldWlen = strlen(oldW); 
        int long_s = READ_LEN;
        // Counting the number of times old word 
        // occur in the string 
        for (i = 0; i < READ_LEN ; i++) 
        { 
            if (strstr(s[i], oldW) == s[i]) 
            { 
                cnt++; 
     
                // Jumping to index after the old word. 
                i += oldWlen - 1; 
            } 
        } 
     
        // Making new string of enough length 
        longueur = i + cnt * (newWlen - oldWlen) + 1; 
     
        i = 0, cnt = 0;
     
        while (cnt < READ_LEN) 
        { 
            // compare the substring with the result 
            if (strstr(s, oldW) == s) 
            { 
                strcpy(&result[i], newW); 
                i += newWlen; 
                cnt += oldWlen; 
            } 
            else
                result[i++] = s[cnt++]; 
        } 
     
     
        return longueur; 
    } 
     
     
    int main(int argc, char *argv[]){
     
     
     
    // Traitement du texte du fichier (sed)
     
     
        char result[2048];
     
     
    	/* OUVERTURE */
        printf("%s %s %s %s\n",argv[0],argv[1],argv[2],argv[3]);
    	int descripteur1= open(argv[3],O_RDONLY,0666);
    	if(descripteur1 ==-1) {
    		perror("Ouverture du fichier source echouee"); 
    		return -1;
    		}
     
    	int descripteur2= open(argv[4],O_WRONLY | O_CREAT , 0666);
    	if(descripteur2 ==-1) {
    		perror("Ouverture du fichier destination echouee");
    		return -1;
    		}
     
    	char buf[READ_LEN];
    	ssize_t nb_lus=0,nb_ecris=0;
        int longueur;
     
    	/* COPIE */
     
    	while((nb_lus = read(descripteur1,buf,1024))>0) {	
            longueur = replaceWord(buf, argv[1], argv[2], result); 			
    		nb_ecris=write(descripteur2, result, longueur);
    		if (nb_ecris==-1) return -1;
    		//nb_lus= read( descripteur1,&buf, 1);
     
    	}
     
    	printf("copie terminee \n");
     
    	/*FERMETURE */
    	if((close(descripteur1)) ==-1) {perror("Fermeture du fichier fichier echouee");return -1;}
    	else{
    		close(descripteur1);
    		if((close(descripteur2))==-1) {perror("Fermeture du fichier destination echouee"); return -1;}
    		else close(descripteur2);
     
    	}
     
    	return 1;	
    }

  2. #2
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 315
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 315
    Billets dans le blog
    5
    Par défaut
    Bonjour.

    Tout d’abord enlève le =C des balises de code pour avoir le bon affichage sur le forum.

    Sans avoir cherché l’erreur j’ai juste regardé la fonction suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    int replaceWord(char * s, char *oldW, char * newW,char *result) 
    { 
    //char result[1024]; 
    int i, cnt, longueur = 0; 
    int newWlen = strlen(newW); 
    int oldWlen = strlen(oldW); 
    int long_s = READ_LEN;
    // Counting the number of times old word 
    // occur in the string 
    for (i = 0; i < READ_LEN ; i++) 
    { 
    if (strstr(s[i], oldW) == s[i]) 
    { 
    cnt++; 
     
    // Jumping to index after the old word. 
    i += oldWlen - 1; 
    } 
    }
    ...
    Lorsque tu transmets des pointeurs à une fonction pense à rendre le plus restrictif possible. Ça te permettra de voir si tu manipules des données en écriture alors que tu n’en as pas le droit.
    Ici s est une chaîne en lecture, il faut donc la déclarer const. La même remarque est aussi applicable à oldW et NewW.

    La fonction strstr(); renvoie l’adresse de la première occurence trouvée ou NULL dans les autres cas. Ton utilisation ne me semble pas correcte. Il vaut mieux écrire if (strstr (s[i], oldW)) ou if (!strstr (s[i], oldW)).

    Il y a bien d’autres remarques pour rendre ton code plus robuste mais j’arrête là pour l’instant 😉.

  3. #3
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 315
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 315
    Billets dans le blog
    5
    Par défaut
    Je reviens vers toi ayant un peu de temps à te consacrer.

    Je reprends la fonction replaceword (); déjà traîtée pour lui ajouter des vérifications :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int replaceWord(const char *s, const char *oldW, const char *newW, char *result) 
    {
      if (!s || !oldW || !newW || !result) {
        fprintf (stderr, "s, oldW, newW and result must be valid pointers in replaceWord (); !\n");
        return -1;
      }
    ...
    Ceci rend encore plus robuste l'utilisation de la fonction. La seule vérification qu'on ne peut pas faire c'est d'être sûr que les chaînes se terminent bien par '\0' et que result est bien alloué pour la longueur nécessaire. Il y a un gros risque de dépassement de tampon ici.

    Une fois cette étape réalisée on progresse un peu dans le code. Tu désires compter le nombre d’occurrences d'un mot dans la phrase contenue dans s.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    for (i = 0; i < READ_LEN ; i++) 
        { 
          if (strstr(s[i], oldW) == s[i]) 
            { 
    	  cnt++; 
     
    	  // Jumping to index after the old word. 
    	  i += oldWlen - 1; 
            } 
        }
    Quelques remarques :
    1. Tu utilises READ_LEN comme longueur de s. Pourquoi pas puisque tu utilises cette valeur pour initialiser une partie de tes buffers. Pourquoi ne pas prendre plutôt la longueur réelle de s qui de toute façon ne dépassera pas READ_LEN ? On gagnerai un peu en temps d’exécution.
    2. Tu incrémentes cnt à chaque fois que tu trouves une occurrence. Sauf que tu ne l'initialises pas avant. Cette variable pourrait tout aussi bien contenir 23 par exemple au départ de la recherche !
    3. Tu utilises strstr ();. J'ai déjà écris quelques lignes à son sujet dans mon premier post. Tu utilises s[i] pensant que tu vas te placer sur l'adresse de s+i. Malheureusement ce n'est pas le cas. En réalité s[i] te donne la valeur de la donnée située en s+i. Utilise plutôt un pointeur temporaire que tu pourras incrémenter pour faire de sauts de mot en mot.
    4. Pour finir avec cette première boucle de recherche, il n'est pas nécessaire d'utiliser une boucle for(); même si ce n'est pas une erreur, il va de soit. On peut utiliser une boucle while qui vérifie que le pointeur temporaire est toujours valide en fonction de sa longueur. On gagne une variable. Ce n'est pas grand chose, mais moins il y en a, mieux on se porte .

    Tout ceci pourrait donner :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    int replaceWord(const char *s, const char *oldW, const char *newW, char *result) 
    {
      if (!s || !oldW || !newW || !result) {
        fprintf (stderr, "s, oldW, newW and result must be valid pointers in replaceWord (); !\n");
        return -1;
      }
     
      int i, cnt=0, longueur = 0; 
      int newWlen = strlen(newW); 
      int oldWlen = strlen(oldW); 
      int long_s = strlen (s);
      // Counting the number of times old word 
      // occur in the string
      const char *text = s;
      while (text < s+long_s)
        { 
          if (strstr(text, oldW))
            { 
    	  cnt++; 
     
    	  // Jumping to index after the old word. 
    	  text += oldWlen - 1; 
            }
         else
            break;
        }
    ...
    Je ne détiens pas la vérité, loin de là. D'autres viendront sûrement modifier ou présenter une autre manière d’appréhender ta problématique. Mais si tu suis ces quelques petits conseils de base, je suis sûr que tu trouveras rapidement les solutions à tes problèmes de gestion mémoire .

  4. #4
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    787
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 787
    Par défaut
    Hello,

    Comme d'habitude, un découpage en fonctions aide. J'y vais de mon petit code, juste pour calculer le nombre d'occurences:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <stdio.h>
    #include <string.h>
     
    int countOccur(char *str,char *searched) {
    	if(*searched==0)
    		return(-1);
    	int count=0;
    	while((str=strstr(str,searched))!=NULL) {
    		count++;
    		str++;
    	}
     
    	return(count);
    }
     
    int main(void) {
    	char *str="aababcabcd";
    	char *searched="bc";			// exemple
     
    	printf("%s se trouve %d fois dans %s\n",searched,countOccur(str,searched),str);
     
    	return(0);
    }

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par edgarjacobs Voir le message
    Comme d'habitude, un découpage en fonctions aide. J'y vais de mon petit code, juste pour calculer le nombre d'occurences
    Pas de parenthèses au return, ce n'est pas une fonction.
    Et puis pourquoi ne pas aérer un peu... ?

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int countOccur(char *str,char *searched) {
    	if (*searched == '\0')
    		return -1;
     
    	int count;
    	for (count=0; (str=strstr(str, searched)) != NULL; count++, str++);
    	return count;
    }
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    787
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 787
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Pas de parenthèses au return, ce n'est pas une fonction.
    J'ai appris (en bonne partie) le C avec le K & R première édition (que je possède toujours). Et dans tous les codes du bouquin, la valeur du return est entre ( ). Ça m'est resté.... Et aussi, sizeof qui n'est pas une fonction, nécessite des ( ) pour les type natifs

    Citation Envoyé par Sve@r Voir le message
    Et puis pourquoi ne pas aérer un peu... ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int countOccur(char *str,char *searched) {
    	if (*searched == '\0')
    		return -1;
     
    	int count;
    	for (count=0; (str=strstr(str, searched)) != NULL; count++, str++);
    	return count;
    }
    L'éternelle discussion: le for() sous-entend que l'on connait le nombre d'éléments à parcourir, le while() sous-entend que l'on s'interrompt pour un événement donné.

  7. #7
    Membre très actif
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 548
    Par défaut
    Bonjour

    Citation Envoyé par Sve@r Voir le message
    Pas de parenthèses au return, ce n'est pas une fonction.

    Sur ce point (cas actuel) , oui pas besoin des parenthèses.

    Cependant, il n'est pas dit ou signifier qu'il ne faut pas mettre des parenthèses. Selon moi ça a du sens de mettre des parenthèses même-si, je vous l'accorde dans le cas présent return ne nécessite pas de parenthèse sur la valeur à retourner.

    En revanche, vous aurez peut-être besoin des parenthèses pour bien signifier que l'ont tien à effectuer l'évaluation d'une expression avec ordre de priorité dont le résultat converti au bon type par return sera renvoyé à l'appelant et justement, le langage de programmation C permet d'utilisation des parenthèse pour modifier ou imposer l'ordre comme dans les mathématiques. Il ne faut pas également oublier que return ne renvoie pas bêtement une valeur ou met fin à une fonction ; return peut parfaitement procéder à l'évaluation d'une expression ; puis la conversion du résultat (valeur) /de l'expression dans le bon type de la fonction (et au passage permettre au compilateur d'émettre un warning si ce n'est pas le bon type attendu dans le cas ou le type que renvoie la fonction est autre que le type des variables traitées dans l'expression/de résult de l'expression) puis il se charge de renvoyer le résultat et terminer la fonction.
    Et si le l'évaluation de l'expression par return contient plusieurs opérateurs son évaluation dépendra alors de l'ordre dans lequel les opérations sont effectuées ainsi donc si l'on procède comme l'exemple ci-dessous, on ne remarquera pas forcément ou du moins pas tout de suite la différence de résultat qui peut avoir un impact et voir considérable selon l'implémentation de l'algorithme permettant la résolution du problème.
    Au final pour le renvoi d'une valeur et une seule valeur; pas besoin de parenthèse mais pour les autres cas et selon la façon dont est implémenté l'algorithme, des parenthèses peuvent être nécessaire.

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
     
     
    int f_foo_a( int x, int y, int z){
        return x + y * z;
    }
     
     
    int f_foo_b( int x, int y, int z){
        return ( x + y) * z;
    }
     
     
    /*
     * un warning sera émis 
     */
    bool f_foo_c( int x, int y, int z){
        return ( x + y) * z;
    }
     
     
     
     
    int main( void ){
     
        /*    Cas 1    */
        if( f_foo_a(1,1,2) == f_foo_b(1,1,2) )
            (void)puts("Vrai");
        else
            (void)puts("FAUX");  /*    oui 3 != 4    */
     
        /*    Cas 2    */
        if( f_foo_a(2,1,2) == f_foo_b(1,1,2) )
            (void)puts("Vrai");    /* oui 4 == 4    */
        else
            (void)puts("FAUX");
     
        return EXIT_SUCCESS;
    }
    À bientôt.

Discussions similaires

  1. [Flex4] erreur non localisée
    Par execrable dans le forum Flex
    Réponses: 1
    Dernier message: 27/04/2011, 11h46
  2. FOP + erreurs non localisées
    Par yozine dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 07/09/2009, 11h05
  3. Erreur de segmentation non trouvée
    Par Bladelight dans le forum OpenCV
    Réponses: 6
    Dernier message: 31/08/2009, 13h40
  4. erreurs de segmentation non détectée
    Par Benoit_T dans le forum Langage
    Réponses: 5
    Dernier message: 21/07/2009, 14h47
  5. Erreur non localisée
    Par nezdeboeuf62 dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 24/01/2008, 22h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo