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 :

segfault sur un cas basique ?


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 14
    Points : 11
    Points
    11
    Par défaut segfault sur un cas basique ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main(int argc, char *argv[])
    {
    char *p="Hello", a[]="Zello";
    
    a[0]='H';
    *(p+0)='Z';
    
    return(0);
    }
    Ok, ça m'a l'air basique et le retourner dans les sens, j'ai une erreur de segmentation sur l'instruction en rouge

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Février 2005
    Messages
    119
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 119
    Points : 192
    Points
    192
    Par défaut
    Salut,
    c'est normal, tu ne peux pas modifier "Hello" (le comportement est non défini).

    Citation Envoyé par N1256
    6.4.5 String literals
    Syntax
    string-literal:
    " s-char-sequenceopt "

    If the program attempts to modify such an array, the behavior is undefined.
    p est un pointeur vers une chaine de caractères (un string literal ici), alors que a est un tableau de caractères que tu initialises avec "Hello".
    Tu peux modifier le contenu de a, mais pas la chaine pointé par p.

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Pour compléter ce que vient de dire gulain, il faut savoir que quand tu fais ça :
    char *p="Hello", aucun espace mémoire n'est réservé sur le tas comme ce serait le cas avec malloc, ou sur la pile comme ce serait le cas avec le tableau a. La chaine "Hello" est mise dans une zone spécifique de la mémoire où sont placées les constantes. Tu ne peux donc pas modifier les données pointées par p, bien que tu puisses modifier p lui-même.

    Mon échange avec gangsoleil dans cette discussion pourra t'intéresser : http://www.developpez.net/forums/d12...n/#post6770934

    PS : char *p="Hello" est une allocation statique : http://fr.wikipedia.org/wiki/Allocation_de_m%C3%A9moire

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 14
    Points : 11
    Points
    11
    Par défaut
    Merci Messieurs pour ces réponses qui sont fondées.
    Je sentais bien l'effet "Constante"

    Aussi, je dois revoir un aspect d'un plus gros programme dans lequel un tableau de pointeurs de char est initialisé avec des chaînes littérales.
    Certaines de ces chaînes sont dynamiquement modifiées.

    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
    #define LEVELS  10
    
    #define MENU_PROMPT_ROOT "[E]xit    [H]elp       [S]how         [D]ump ___________________"
    ...
    #define MENU_PROMPT_MEMY "[<]Back   [A]rray ____________________________"
    
    #define LV_ROOT 0
    ...
    #define LV_ATTY 8
    #define LV_STRY 9
    
    
    char *menuPrompt[LEVELS]=
    {
    MENU_PROMPT_ROOT,
    ...
    MENU_PROMPT_MEMY,
    MENU_PROMPT_MEMY
    };
    
    menuPrompt[LV_ATTY][23]='[';
    Bon pour du malloc, dommage je l'aimais bien cette souplesse d'assignation

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 14
    Points : 11
    Points
    11
    Par défaut
    Résolu par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char menuPrompt[LEVELS][66]=
    {
    MENU_PROMPT_ROOT,
    ...
    MENU_PROMPT_MEMY,
    MENU_PROMPT_MEMY
    };
    En revanche, cela implique une longueur = 66 char pour toutes les littérales, voire > 66 avec warning du compilateur.
    Et < à 66, ça tappe dans l'inconnu

  6. #6
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Cela implique une longueur inférieure ou égale à 65 (66 avec le caractère de fin de chaine), plutôt ?

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 14
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Pour compléter ce que vient de dire gulain, il faut savoir que quand tu fais ça :
    char *p="Hello", aucun espace mémoire n'est réservé sur le tas comme ce serait le cas avec malloc, ou sur la pile comme ce serait le cas avec le tableau a. La chaine "Hello" est mise dans une zone spécifique de la mémoire où sont placées les constantes. Tu ne peux donc pas modifier les données pointées par p, bien que tu puisses modifier p lui-même.

    Mon échange avec gangsoleil dans cette discussion pourra t'intéresser : http://www.developpez.net/forums/d12...n/#post6770934

    PS : char *p="Hello" est une allocation statique : http://fr.wikipedia.org/wiki/Allocation_de_m%C3%A9moire
    J'ai lu cette discussion, merci ; et sans vouloir insister cela fut il toujours le cas ?
    En effet, j'ai souvenir du compilateur Turbo C qui autorisait ce genre de réécriture !

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Février 2005
    Messages
    119
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 119
    Points : 192
    Points
    192
    Par défaut
    Citation Envoyé par CyrIng Voir le message
    J'ai lu cette discussion, merci ; et sans vouloir insister cela fut il toujours le cas ?
    En effet, j'ai souvenir du compilateur Turbo C qui autorisait ce genre de réécriture !
    Le comportement n'est pas défini, ça veut dire que le compilateur fait ce qu'il veut, en particulier il peut faire en sorte que tu puisses modifier ces chaînes de caractères (c'était peut-être le cas de Turbo C, je n'en sais rien).

  9. #9
    Membre confirmé

    Profil pro
    Inscrit en
    Août 2007
    Messages
    178
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 178
    Points : 451
    Points
    451
    Par défaut
    Sinon il y a strdup de la bibliothèque string.h qui fait à la fois l'allocation mémoire et l'assignation

    Si tu remplaces
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *p=strdup("Hello")
    tu n'auras plus ton erreur de segmentation

    Cette fonction n'est pas standard, mais malgré tout assez portable puisque POSIX.1.

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 14
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par pythéas Voir le message
    Sinon il y a strdup de la bibliothèque string.h qui fait à la fois l'allocation mémoire et l'assignation

    Si tu remplaces
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *p=strdup("Hello")
    tu n'auras plus ton erreur de segmentation

    Cette fonction n'est pas standard, mais malgré tout assez portable puisque POSIX.1.
    Merci, je la garde sous le coude; mais depuis les heures ont coulé et par rage j'ai tout changé pour des tableaux à taille fixe
    En fait je souhaitais définir dans le header file, une matrice de hauteur et de largeur résolues par le compilateur, avec surtout pour chaque ligne, un nombre variable de colonnes.

    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
    #include <stdio.h>
    int main(int argc, char *argv[])
    {
        int  x=0, y=0;
     
        char *M[]=
        {
            "1234567890$",
            "123$",
            "abcdefgh$",
            "%"
        };
     
        while(M[y][x]!='%')
        {
            while(M[y][x]!='$')
            {
                printf("%c",M[y][x]);
                x++;
            }
            printf("\n");
            x=0;
            y++;
        }
        return(0);
    }
    Où '$' et '%' sont les délimiteurs scannés par les boucles.

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 14
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par CyrIng Voir le message
    Merci, je la garde sous le coude; mais depuis les heures ont coulé et par rage j'ai tout changé pour des tableaux à taille fixe
    En fait je souhaitais définir dans le header file, une matrice de hauteur et de largeur résolues par le compilateur, avec surtout pour chaque ligne, un nombre variable de colonnes.

    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
    #include <stdio.h>
    int main(int argc, char *argv[])
    {
        int  x=0, y=0;
     
        char *M[]=
        {
            "1234567890$",
            "123$",
            "abcdefgh$",
            "%"
        };
     
        while(M[y][x]!='%')
        {
            while(M[y][x]!='$')
            {
                printf("%c",M[y][x]);
                x++;
            }
            printf("\n");
            x=0;
            y++;
        }
        return(0);
    }
    Où '$' et '%' sont les délimiteurs scannés par les boucles.
    Maintenant on y ajoute la réécriture et " Segmentation fault "

    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
    #include <stdio.h>
    int main(int argc, char *argv[])
    {
        int  x=0, y=0;
    
        char *M[]=
        {
            "1234567890$",
            "123$",
            "abcdefgh$",
            "%"
        };
    
        while(M[y][x]!='%')
        {
            while(M[y][x]!='$')
            {
                printf("%c",M[y][x]);
                x++;
            }
            printf("\n");
            x=0;
            y++;
        }
        M[2][3]='C';
        return(0);
    }

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2012
    Messages : 10
    Points : 13
    Points
    13
    Par défaut
    C'est le même problème sauf que dans ce cas au lieu d'avoir un pointeur vers une chaine de caractères, tu as un tableau de pointeurs vers des chaines de caractères.
    Tu essaies donc toujours de modifier des chaines constantes.

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 14
    Points : 11
    Points
    11
    Par défaut
    J'ai bien compris. Thanks

    J'ai adapté en conséquence pour achever mon soft CoreMod : lecture des registres du Core i7 et de la DMI BIOS

    Les sources sont dans mon Wiki et des copies d'écran dans le blog

    Maintenant au dodo

Discussions similaires

  1. Segfault sur un int?
    Par lguignar dans le forum Débuter
    Réponses: 9
    Dernier message: 18/07/2008, 10h03
  2. Segfault sur un int?
    Par lguignar dans le forum C++
    Réponses: 9
    Dernier message: 18/07/2008, 10h03
  3. Segfault sur contructeur de string
    Par lemmel dans le forum SL & STL
    Réponses: 7
    Dernier message: 02/09/2007, 13h50
  4. Avis sur un cas simple de diagramme de classe
    Par arnobidul dans le forum Diagrammes de Classes
    Réponses: 8
    Dernier message: 01/08/2007, 09h07
  5. [LG]plantage sur une commande basique !
    Par Jeff on the web dans le forum Langage
    Réponses: 5
    Dernier message: 13/01/2004, 19h07

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