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 :

pourquoi j'ai une segmentation fault


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    Homme Profil pro
    amateur
    Inscrit en
    Mars 2015
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Mars 2015
    Messages : 17
    Par défaut pourquoi j'ai une segmentation fault
    salut à tous et à toutes
    je ne sais pas pourquoi j'obtiens une segmentation faulte, alors que une zone mémoire est crée et l'adresse du début de cette zone a été passé à un pointeur.
    avant de passer à la saisie caractère par caractère j'ai essayé de saisir la chaîne de caractère en un seul coup avec cette instruction:
    mais malheureusement j'ai obtenu une segmentation faute.
    pourquoi cela passe avec les tableaux mais pas avec les pointeurs.
    je cherche à comprendre
    si quelqu'un peut m'éclaircir
    Merci beaucoup pour votre aide
    cordialement
    Nom : segmentation fault.jpg
Affichages : 1333
Taille : 142,4 Ko

  2. #2
    Membre émérite
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Par défaut
    Bonjour,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *chaine="Hello friends";
    La chaîne "Hello friends" est une chaîne littérale, cela signifie qu'elle sera stockée dans une zone en lecture seule en mémoire. Tu essayes de la modifier → seg fault.
    Pour que «cela passe avec des pointeurs» il faut allouer manuellement la mémoire pointée avec malloc par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *chaine = malloc( 1000 * sizeof(char) );
    permet d'allouer une zone pouvant contenir 1000 objets de type char. Ici le sizeof(char) n'est pas nécessaire puisque par définition il vaut 1.

    Ah … et pour insérer du code, utilise les balises codes …

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
              scanf( "%c", chaine[j] );
    Le paramètre que tu passes à scanf est la valeur de chaine[j] qui est un char. Pour toutes les fonctions, les paramètres char ou short sont convertis en int, les paramètres float sont convertis en double. Mais le "%c" suppose un paramètre de type adresse d'un char. D'où le message d'avertissement.

    Et que cherches tu à faire en écrivant?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
              scanf( "%c", chaine[j] );
              getchar();
    La première ligne va lire un caractère, la seconde va aussi lire un caractère.

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

    Informations professionnelles :
    Activité : Développeur informatique

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

    @WhiteCrow: on peut se passer de malloc(). Il suffit d'écrire char str[]="Hello friends";

  5. #5
    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 edgarjacobs Voir le message
    Hello,

    @WhiteCrow: on peut se passer de malloc(). Il suffit d'écrire char str[]="Hello friends";
    Attention tout de même; cela fonctionne mieux avec un garde-fou qui permet d'éviter tout débordement de la pile ou UB
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
     
     
    int main( void ){
     
     
        size_t size_buff = 0x0;
        char buff[] = "babidy";
     
        /*
        *   Warning: error handling 
        *   and function return is voluntarily ignored
        */
        if( 0x0 >= (size_buff = strlen(buff)) ){
            (void)fprintf(stderr,"Error\t:Wrong input size");
            return EXIT_FAILURE;
        }
     
        (void)fgets(buff, size_buff, stdin);
        return EXIT_SUCCESS;
    }
    à bientôt

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    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 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sambia39 Voir le message
    Attention tout de même; cela fonctionne mieux avec un garde-fou qui permet d'éviter tout débordement de la pile ou UB
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    if( 0x0 >= (size_buff = strlen(buff)) )...
    Si je comprends bien le principe de ton "garde fou", tu lis la string (oui, strlen() lit la string pour y chercher le '\0') au cas où celle-ci n'aurait pas été allouée et serait de fait illisible
    De fait, quand j'ai tenté ton code avec un char [50000000] j'ai eu un segfault..
    Accessoirement tester un size_t (toujours positif) comme pouvant être éventuellement < 0...

    Citation Envoyé par sambia39 Voir le message
    (void)fprintf(...)
    T'as toujours pas appris ce qu'était le cast implicite toi !!!
    Sinon super ta coloration syntaxique. Comme ça, celui qui veut répondre à ton post il en a plein les doigts...
    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]

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    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 833
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par math25 Voir le message
    pourquoi cela passe avec les tableaux mais pas avec les pointeurs.
    Quand tu écris char chaine[]="Hello", tu définis un tableau de char qui t'es dédié. Dans ce tableau tu peux faire ce que tu veux. Y compris si tu déclares un pointeur char *pt=chaine tu peux alors utiliser indifféremment "chaine" ou "pt". Ce n'est donc pas à cause du pointeur.
    Quand tu écris char *chaine="Hello", tu définis une string contenant "Hello" située dans un emplacement non modifiable de ton code et tu récupères l'adresse de cet emplacement que tu stockes dans le pointeur "chaine". Tu peux toujours te ballader à cette adresse et aux suivantes et regarder ce qu'il y a (donc en résumé lire la zone) mais tu ne peux pas la modifier.

    Citation Envoyé par WhiteCrow Voir le message
    Ici le sizeof(char) n'est pas nécessaire puisque par définition il vaut 1.
    C'est quand-même plus prudent de le laisser au cas où ça change un jour...

    Citation Envoyé par dalfab Voir le message
    Et que cherches tu à faire en écrivant?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
              scanf( "%c", chaine[j] );
              getchar();
    La première ligne va lire un caractère, la seconde va aussi lire un caractère.
    Je verrais bien là une astuce donnée par son prof pour bouffer le <return> qui a été tapé à la saisie dudit caractère...
    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]

  8. #8
    Membre actif
    Homme Profil pro
    amateur
    Inscrit en
    Mars 2015
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Mars 2015
    Messages : 17
    Par défaut
    merci beaucoup pour vos réponses
    pour la ligne 11 je devrais écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    scanf("%c",chaine+j);
    comme ça scanf va recevoir une adresse à chaque passage de la boucle FOR. donc le warning va disparaître.
    mais cela ne va pas résoudre le problème puisque la zone mémoire crée pour ranger la chaîne de caractère est en lecture seul (d'après WhiteCrow).
    je peux créer une autre chaine de caractère avec ce code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    chaine="thank you very much";
    dans ce cas une autre zone mémoire va recevoir la nouvelle chaîne de caractère et l'adresse de début de cette zone sera passée au pointeur chaine
    donc la valeur du pointeur sera modifiée
    merci encore une deuxième fois.
    vous m'avez aidé à comprendre tout cela.

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    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 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par math25 Voir le message
    pour la ligne 11 je devrais écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    scanf("%c",chaine+j);
    comme ça scanf va recevoir une adresse à chaque passage de la boucle FOR. donc le warning va disparaître.
    Exact (j'avais pas vu l'erreur du premier code). Tu peux aussi appliquer l'équivalence de l'arithmétique des pointeurs et écrire scanf("%c", &chaine[j]). Les deux écritures sont absolument équivalentes et la seconde est (avis personnel) un peu plus lisible.

    Citation Envoyé par math25 Voir le message
    mais cela ne va pas résoudre le problème puisque la zone mémoire crée pour ranger la chaîne de caractère est en lecture seul (d'après WhiteCrow).
    Et d'après beaucoup d'autres aussi

    Citation Envoyé par math25 Voir le message
    je peux créer une autre chaine de caractère avec ce code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    chaine="thank you very much";
    dans ce cas une autre zone mémoire va recevoir la nouvelle chaîne de caractère et l'adresse de début de cette zone sera passée au pointeur chaine
    donc la valeur du pointeur sera modifiée
    Exact, tout comme tu peux écrire int i; i=100; i=200 tu peux écrire char *chaine; chaine="toto"; chaine="titi". Dans la première écriture tu modifies une variable prévue pour stocker un entier et dans la seconde tu modifies une variable prévue pour stocker une adresse. Mais attention, la première chaine "toto" n'a pas disparu. Simplement toi tu auras perdu son adresse. Généralement c'est peu fréquent de créer une chaine pour la perdre 3 lines plus bas...
    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]

  10. #10
    Membre actif
    Homme Profil pro
    amateur
    Inscrit en
    Mars 2015
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Mars 2015
    Messages : 17
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Mais attention, la première chaine "toto" n'a pas disparu. Simplement toi tu auras perdu son adresse. Généralement c'est peu fréquent de créer une chaine pour la perdre 3 lines plus bas...
    merci beaucoup pour cette information. vraiment elle est très utile.
    avec ce code simple on peut vérifier que la zone mémoire réservée pour stocker la 1ère chaine de caractère n'est pas libérée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    #include <stdio.h>
    #include <stdlib.h>
     
    int main()
    {
        char *pt, *chaine="chaine de caractere 1";
        pt=chaine;
        chaine="une deuxieme chaine de caractere";
        printf("%s\n", pt);
        return 0;
    }
    malheureusement, ces détails n'existent pas dans les livres. on apprend les détails seulement en programmant et lorsqu'on cherche des explications.
    Merci beaucoup

  11. #11
    Membre émérite
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Par défaut
    Citation Envoyé par edgarjacobs Voir le message
    Hello,

    @WhiteCrow: on peut se passer de malloc(). Il suffit d'écrire char str[]="Hello friends";
    Ah tient, je n'avais pas vu … en fait je ne parlais que de «le faire avec des pointeurs» et non des tableaux …

    Citation Envoyé par WhiteCrow Voir le message
    Bonjour,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *chaine="Hello friends";
    La chaîne "Hello friends" est une chaîne littérale, cela signifie qu'elle sera stockée dans une zone en lecture seule en mémoire. Tu essayes de la modifier → seg fault.
    Pour que «cela passe avec des pointeurs» il faut allouer manuellement la mémoire pointée avec malloc par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *chaine = malloc( 1000 * sizeof(char) );
    permet d'allouer une zone pouvant contenir 1000 objets de type char. Ici le sizeof(char) n'est pas nécessaire puisque par définition il vaut 1.

    Ah … et pour insérer du code, utilise les balises codes …

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Pourquoi ce code plante (segmentation fault)
    Par fcjunic dans le forum Débuter
    Réponses: 3
    Dernier message: 19/01/2011, 12h05
  2. free() qui provoque une segmentation fault
    Par bringer dans le forum Débuter
    Réponses: 16
    Dernier message: 19/11/2010, 17h46
  3. pourquoi 'segmentation fault'?
    Par thepinguin dans le forum C
    Réponses: 25
    Dernier message: 21/11/2006, 22h23
  4. Segmentation fault : pourquoi ?
    Par Dan_coyle dans le forum C
    Réponses: 5
    Dernier message: 23/04/2006, 20h26
  5. Réponses: 6
    Dernier message: 13/11/2005, 12h11

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