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

  1. #1
    Futur Membre du Club
    Homme Profil pro
    amateur
    Inscrit en
    mars 2015
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : mars 2015
    Messages : 6
    Points : 5
    Points
    5
    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 : 135
Taille : 142,4 Ko

  2. #2
    Membre averti
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    juillet 2020
    Messages
    100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : juillet 2020
    Messages : 100
    Points : 301
    Points
    301
    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 éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    décembre 2015
    Messages
    1 254
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 254
    Points : 6 096
    Points
    6 096
    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 éprouvé Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    mai 2011
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : mai 2011
    Messages : 448
    Points : 1 096
    Points
    1 096
    Par défaut
    Hello,

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

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 910
    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 : 8 910
    Points : 24 448
    Points
    24 448
    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 «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  6. #6
    Futur Membre du Club
    Homme Profil pro
    amateur
    Inscrit en
    mars 2015
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : mars 2015
    Messages : 6
    Points : 5
    Points
    5
    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.

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 910
    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 : 8 910
    Points : 24 448
    Points
    24 448
    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 «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  8. #8
    Futur Membre du Club
    Homme Profil pro
    amateur
    Inscrit en
    mars 2015
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : mars 2015
    Messages : 6
    Points : 5
    Points
    5
    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

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 910
    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 : 8 910
    Points : 24 448
    Points
    24 448
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par math25 Voir le message
    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:
    Absolument pas. Tout ce que tu fais c'est copier "chaine" (une adresse) dans "pt" (une variable prévue pour recevoir une adresse). Au final tu obtiens juste une adresse (une valeur) copiée que tu affiches ensuite. Qu'est ce qui te dit que la zone en question a/n'a pas été libérée ? Comment à ton avis se "matérialiserait" cette libération? Tous les caractères mis à 0? à blanc?? à 0xff??? Mais surtout pourquoi faire??? Pourquoi un mécanisme destiné à libérer une zone, c'est à dire à indiquer à un organisme de contrôle que la zone est libre (donc disponible pour qui veut y écrire des trucs) s'embêterait à la remplir par des valeurs qui de toute façon seront écrasées par le prochain à l'utiliser??? Ou (dans l'autre sens) pourquoi il irait mettre des caractères dans une zone qui déjà est read-only et surtout qui, de toute façon, a été perdue (donc est devenue irrécupérable)? Ou alors (3° axe de réflexion) pourquoi y devrait-il y avoir lbération puisque le truc qui gère la libération pourrait conclure que comme tu as pris soin de récupérer l'adresse alors la string n'est donc pas perdue?

    Faut se méfier des conclusions trop rapides. Le C ne fait jamais rien d'inutile. Ni même jamais aucun contrôle de ce qui est autorisé ou pas. C'est sa force (il va le plus vite possible) mais aussi sa faiblesse (à toi de ne pas coder des trucs "logiquement" impossibles car tu tombes dans le comportement indéterminé c.a.d. imprévisible). Typiquement, essayer d'afficher un truc que tu pense être libéré, ça entre dans la liste des comportements indéterminés.
    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

  10. #10
    Membre chevronné
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    mai 2010
    Messages
    523
    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 : 523
    Points : 1 870
    Points
    1 870
    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
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  11. #11
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 910
    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 : 8 910
    Points : 24 448
    Points
    24 448
    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 «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  12. #12
    Membre averti
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    juillet 2020
    Messages
    100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : juillet 2020
    Messages : 100
    Points : 301
    Points
    301
    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 …

  13. #13
    Membre chevronné
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    mai 2010
    Messages
    523
    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 : 523
    Points : 1 870
    Points
    1 870
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    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...
    Si j'ai bien compris, tu obtiens un segfault avec un buffer ayant une taille 50000000 sans te poser la question de savoir si la taille sollicitée ne serait peut-être pas à l'origine de ton segfault ?
    Aussi, il ne faut pas que tu sous-entendes ce que j'ai préalablement écrit(p
    récèdent post) . Certes j'ai spécifié qu'il faut un garde-fou, mais dans un contexte qui est celui de la saisie de données, en partant du constat que l'on peut se passer d'une allocation dynamique.

    Citation Envoyé par Sve@r Voir le message
    Accessoirement tester un size_t (toujours positif) comme pouvant être éventuellement < 0...


    Un point que je pourrais te l'accorder. J'ai mal écrit l'expression de mon "if", mais techniquement et c'est différent d'un == mis à part la façon dont il écrit ?

    Citation Envoyé par Sve@r Voir le message
    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...
    Tu as du mal avec mon (void) et d'ailleurs, ce n’est pas la première fois que je te le dis. Si un programmeur fait particulièrement attention à toujours vérifier les conditions d'erreur à chaque endroit où des erreurs peuvent se produire, alors il peut explicitement faire (void) et donc signifier le compilateur qu'il ignore la valeur retour ou signifie l'absence de contrôle d'erreur et donc l'absence de vérification d'erreur. Ce n'est donc pas un style d'écriture ou oublie, mais une décision de conception délibérée (volontaire).

    Citation Envoyé par Sve@r Voir le message
    Sinon super ta coloration syntaxique. Comme ça, celui qui veut répondre à ton post il en a plein les doigts...

    Ai-je écrit avec un pot de peinture ?

    à bientôt
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  14. #14
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 910
    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 : 8 910
    Points : 24 448
    Points
    24 448
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sambia39 Voir le message
    Si j'ai bien compris, tu obtiens un segfault avec un buffer ayant une taille 50000000 sans te poser la question de savoir si la taille sollicitée ne serait peut-être pas à l'origine de ton segfault ?
    Ben évidemment que si, je sais parfaitement que c'est mon 50 millions de char dans la pile qui provoque le segfault
    Mais à quoi sert un "garde-fou" si on ne peut pas le tester... ou alors c'est un garde-fou qui ne fonctionne que si on ne peut pas le tester. Tout comme cet avocat qui a voulu tester la vitre sécurisée de son bureau du 24° étage et qui est passé à travers... https://hitek.fr/bonasavoir/meurt-de...incassable_132...

    Citation Envoyé par sambia39 Voir le message
    Aussi, il ne faut pas que tu sous-entendes ce que j'ai préalablement écrit(précèdent post) . Certes j'ai spécifié qu'il faut un garde-fou, mais dans un contexte qui est celui de la saisie de données, en partant du constat que l'on peut se passer d'une allocation dynamique.
    Intéressant. Tu veux bien m'indiquer alors, dans le cadre d'une saisie de données, dans quelle condition l'instruction if( 0x0 >= (size_buff = strlen(buff)) ) détectera (enfin je pars de l'hypothèse que c'est son but) un souci? Je sais pas, j'essaye d'imaginer. L'utilisateur saisit trop? Dans ce cas la saisie (y compris son trop plein) a déjà été stockée dans la zone trop petite et on est déjà dans le UB, avant même d'avoir pu faire le test. Et même dans ce cas size_buf n'est pas à 0. L'utilisateur ne saisit pas assez? Dans ce cas la zone est remplie avec le peu de ce qui a été saisi et size_buf n'est de toute façon pas non plus à 0. En fait les deux seuls moments où size_buf pourra être à 0 (tu as admis qu'il ne pouvait pas être <0 donc on n'en parle plus) c'est soit la zone commence par un '\0' (donc elle est vide mais ce n'est pas une preuve d'un souci quelconque) soit elle est tellement longue que sa taille vaut pile poil la valeur max du size_t +1. Mais là encore je ne vois pas trop en quoi détecter cet êtat sera synonyme de souci. Ou plutôt oui, ce sera effectivement un souci que d'avoir une string aussi longue mais détecter ce souci particulier sera vraiment peanut face à tous les autres soucis possibles qui, eux, n'auront pas été détectés par ce test.
    Accessoirement moi quand je fais de la saisie, je conseille de passer par un buffer de taille X (peu importe le X pourvu qu'il soit taillé de façon sensée) et de le remplir avec un fgets(buffer, X, stdin) comme ça c'est fgets() qui sert de garde-fou.

    Citation Envoyé par sambia39 Voir le message
    Tu as du mal avec mon (void) et d'ailleurs, ce n’est pas la première fois que je te le dis. Si un programmeur fait particulièrement attention à toujours vérifier les conditions d'erreur à chaque endroit où des erreurs peuvent se produire, alors il peut explicitement faire (void) et donc signifier le compilateur qu'il ignore la valeur retour ou signifie l'absence de contrôle d'erreur et donc l'absence de vérification d'erreur. Ce n'est donc pas un style d'écriture ou oublie, mais une décision de conception délibérée (volontaire).
    Dans ce cas pourquoi s'arrêter en si bon chemin? Tu n'es certainement pas sans savoir que toute affectation renvoie la valeur affectée. C'est grâce à ça qu'on peut écrire des trucs comme x=y=z=123. Donc quand tu affectes (mettons 123) à "i", pourquoi n'écris-tu pas (void)(i=123) pour là aussi montrer que tu ne veux délibérément ignorer la valeur résiduelle de cette affectation??? Faut être logique avec toi-même quoi.
    Donc moi je laisse le cast implicite le signifier pour moi au compilo car c'est une possibilité elle-aussi délibérément implantée dans le langage donc autant en profiter. Ca permet d'écrire un code moins chargé donc moins âpre à relire et tout aussi fonctionnel et pas moins robuste.

    Citation Envoyé par sambia39 Voir le message
    Ai-je écrit avec un pot de peinture ?
    T'as qu'à faire un "répondre avec citation" sur ton précédent post et tu constateras par toi-même...

    Citation Envoyé par sambia39 Voir le message
    à bientôt
    J'en suis sûr
    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

  15. #15
    Membre chevronné
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    mai 2010
    Messages
    523
    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 : 523
    Points : 1 870
    Points
    1 870
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ben évidemment que si, je sais parfaitement que c'est mon 50 millions de char dans la pile qui provoque le segfault
    Évidemment. Sérieusement tu vas me faire croire que tu le savais ?

    Citation Envoyé par Sve@r Voir le message
    Dans ce cas pourquoi s'arrêter en si bon chemin? Tu n'es certainement pas sans savoir que toute affectation renvoie la valeur affectée. C'est grâce à ça qu'on peut écrire des trucs comme x=y=z=123. Donc quand tu affectes (mettons 123) à "i", pourquoi n'écris-tu pas (void)(i=123) pour là aussi montrer que tu ne veux délibérément ignorer la valeur résiduelle de cette affectation??? Faut être logique avec toi-même quoi.
    Donc moi je laisse le cast implicite le signifier pour moi au compilo car c'est une possibilité elle-aussi délibérément implantée dans le langage donc autant en profiter. Ca permet d'écrire un code moins chargé donc moins âpre à relire et tout aussi fonctionnel et pas moins robuste.

    J’aimerais bien que tu m’expliques où est-ce que je parle d’affectation; contrairement au fait que j’ai explicitement écrit valeur retour de fonction et gestion d’erreur concernant mon (void)


    Aussi, explique-moi, ce que tu n’as pas compris concernant l’expression de l’if qui a pour tâche de determiner la taille du buffer dynamiquement; afin de borner la saisie et ainsi éviter un overflow. Et que dans mon l'exemple; buffer est écrit char buff[]="babidy" contrairement à char [50000000]; ou peut être char buff[50] = "babidy".

    Question: char buff[50000000] ou char [50000000] est dans mon exemple ou ce que @edgarjacobs a écrit ?.


    à bientôt.
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  16. #16
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 910
    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 : 8 910
    Points : 24 448
    Points
    24 448
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sambia39 Voir le message
    Évidemment. Sérieusement tu vas me faire croire que tu le savais ?
    Ah, tu es le premier depuis que je suis sur ce forum (2006) à m'accuser de mensonge (et je ne me souviens pas avoir vu quiconque faire de même avec quiconque). Les autres lecteurs apprécieront ton état d'esprit.
    Donc va lire ce post qui date de 2018, ou bien cet autre qui date de 2015 et dans lesquels je parle de la pile et de sa taille limitée. Ensuite, si ça t'amuse, tu pourras toujours chercher ceux qui montreraient le contraire, pauvre type.

    Citation Envoyé par sambia39 Voir le message
    J’aimerais bien que tu m’expliques où est-ce que je parle d’affection; contrairement au fait que j’ai explicitement écrit valeur retour de fonction et gestion d’erreur concernant mon (void)
    J'ai généralisé. Si tu castes le retour de printf() en void, c'est pour shunter ce qu'elle renvoie. J'ai donc appliqué ce principe à tout ce qui est susceptible de renvoyer une valeur. Et je ne vois pas le lien entre caster printf() en void et la gestion des erreurs.

    Citation Envoyé par sambia39 Voir le message
    Aussi, explique-moi, ce que tu n’as pas compris concernant l’expression de l’if qui a pour tâche de determiner la taille du buffer dynamiquement; afin de borner la saisie et ainsi éviter un overflow. Et que dans mon l'exemple; buffer est écrit char buff[]="babidy" contrairement à char [50000000]; ou peut être char buff[50] = "babidy".
    T'es une vraie brouette toi. Je te l'ai détaillé dans les différentes possibilités que j'énumère pour tenter d'arriver à avoir ce "if" vrai, et auxquelles tu n'as pas répondu. Donc je recommence en plus simple: en quoi tester si strlen(buff) vaut 0 va protéger quoi que ce soit et éviter un overflow?

    Citation Envoyé par sambia39 Voir le message
    Question: char buff[50000000] ou char [50000000] est dans mon exemple ou ce que @edgarjacobs a écrit ?.
    Non, comme je te l'ai dit j'ai juste extrapolé ton exemple (et non pas celui d'edgarjacobs car lui il n'a pas écrit une grosse connerie) pour te montrer que ton garde-fou en fait ne garde que dalle. Mais si chaque fois que tu donnes un exemple et que quelqu'un arrive en te disant que dans telle situation ton exemple ne fonctionne pas tu lui réponds "les valeurs de ta situation ne sont pas celles que j'ai écrites" on n'avancera pas. Un exemple est fait pour illustrer une méthode, méthode que l'on peut alors généraliser dans des configurations diverses. Sinon ton exemple illustre que dalle.
    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

  17. #17
    Membre chevronné
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    mai 2010
    Messages
    523
    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 : 523
    Points : 1 870
    Points
    1 870
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ah, tu es le premier depuis que je suis sur ce forum (2006) à m'accuser de mensonge (et je ne me souviens pas avoir vu quiconque faire de même avec quiconque). Les autres lecteurs apprécieront ton état d'esprit.
    Donc va lire ce post qui date de 2018, ou bien cet autre qui date de 2015 et dans lesquels je parle de la pile et de sa taille limitée. Ensuite, si ça t'amuse, tu pourras toujours chercher ceux qui montreraient le contraire, pauvre type.

    J'ai généralisé. Si tu castes le retour de printf() en void, c'est pour shunter ce qu'elle renvoie. J'ai donc appliqué ce principe à tout ce qui est susceptible de renvoyer une valeur. Et je ne vois pas le lien entre caster printf() en void et la gestion des erreurs.
    Celui qui dit qui est et ta calvitie ne t’aide pas . Tu n’as rien généralisé; dans le cas présent tu veux absolument avoir raison. En terme plus simple une justification sur un strlen(buff) en le sortant de son context.

    Citation Envoyé par Sve@r Voir le message
    T'es une vraie brouette toi. Je te l'ai détaillé dans les différentes possibilités que j'énumère pour tenter d'arriver à avoir ce "if" vrai, et auxquelles tu n'as pas répondu. Donc je recommence en plus simple: en quoi tester si strlen(buff) vaut 0 va protéger quoi que ce soit et éviter un overflow?
    Soit char buff[] = "babidy"; si strlen(buff) vaut zéro; il n’y aura pas de saisie de caractère et donc rien du tout (pas de débordement donc pas saisie de caractère).
    Si strlen(buffer) different de zéro (donc nombre de caractère determiner); le résultat de strlen(buff) est mise dans size_buff. Puis size_buff est transmis comme second argument à fgets pour permettre à la fonction (fgets) de connaitre le nombre de caractères à lire là aussi pas de débordement.


    Je ne peux pas faire plus simple à un mulet....



    Citation Envoyé par Sve@r Voir le message
    Non, comme je te l'ai dit j'ai juste extrapolé ton exemple (et non pas celui d'edgarjacobs car lui il n'a pas écrit une grosse connerie) pour te montrer que ton garde-fou en fait ne garde que dalle. Mais si chaque fois que tu donnes un exemple et que quelqu'un arrive en te disant que dans telle situation ton exemple ne fonctionne pas tu lui réponds "les valeurs de ta situation ne sont pas celles que j'ai écrites" on n'avancera pas. Un exemple est fait pour illustrer une méthode, méthode que l'on peut alors généraliser dans des configurations diverses. Sinon ton exemple illustre que dalle.
    Incorrect. Un exemple est un cas antérieur semblable ou comparable à ce dont il s'agit et non une extrapolation qui est de tirer des conclusions à partir de données partielles.
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  18. #18
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 910
    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 : 8 910
    Points : 24 448
    Points
    24 448
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sambia39 Voir le message
    Soit char buff[] = "babidy"; si strlen(buff) vaut zéro; il n’y aura pas de saisie de caractère et donc rien du tout (pas de débordement donc pas saisie de caractère).
    Si strlen(buffer) different de zéro (donc nombre de caractère determiner); le résultat de strlen(buff) est mise dans size_buff. Puis size_buff est transmis comme second argument à fgets pour permettre à la fonction (fgets) de connaitre le nombre de caractères à lire là aussi pas de débordement.
    Je ne peux pas faire plus simple à un mulet....
    Non, désolé, non, si char buff[]="babidy" alors strlen(buff) ne peut pas valoir zéro. J'ai beau le tourner dans tous les contextes du monde, je ne vois pas comment strlen(buff) peut valoir 0. Ou alors... ou alors c'est si tu écris plus tard char buff[]=""? Ce serait ça ton "garde-fou"??? Alors là les bras m'en tombent. Tu es vraiment en train de dire à la communauté des devs du C "hey les gars, si vous programmez comme des débiles j'ai la solution"??? Ou alors c'est pour math25 qui débute que tu as pondu cette... bouse? Pour lui dire "hey mon gars, tu débutes tu risques de faire des erreurs mais t'inquiète pas, voici un test qui va te protéger"? Et que se passera-t-il s'il suit tes conseils et qu'il écrit (comme dans ton post précédent) char buff[50]="babidy"??? 50 caractères offerts mais seulement 6 à pouvoir être saisis!!! Sans déconner t'es un vrai danger public du C toi!!!

    Désolé mais même comme ça, ton code sert à que dalle. Parce que même si on ne teste pas size_buff == 0, le fgets() suivant, lui, empêchera la saisie, pour peu qu'on l'écrive correctement. Car c'est fgets(buff, size_buff+1, stdin) qu'il faut écrire (hé oui, fgets() enlève systématiquement 1 à la taille qu'on lui donne pour pouvoir y stocker le '\0').

    Donc si on réécrit ton code ainsi...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main(void ){
     
    	char buff[] = "babidy";
    	size_t size_buff = strlen(buff);
     
    	(void)fgets(buff, size_buff + 1, stdin);
    	return EXIT_SUCCESS;
    }
    ... il fonctionnera absolument sans UB, y compris si on écrit ensuite char buff[] = "". Je ne dis pas que dans ce cas il produira le résultat escompté mais au-moins on ne sera pas dans le UB que ton test était censé (si j'en crois ton premier post) protéger car fgets() limitera elle-même la saisie pour ne pas dépasser.

    Bien la preuve que ton "garde-fou" sert à que dalle. Ou plutôt si, il te sert probablement à toi seul car tu dois être le seul à te penser assez con pour écrire un jour char buff[]="" et à te demander comment t'en protéger.

    Citation Envoyé par sambia39 Voir le message
    Incorrect. Un exemple est un cas antérieur semblable ou comparable à ce dont il s'agit et non une extrapolation qui est de tirer des conclusions à partir de données partielles.
    Tu t'enfonces là. Donc ton exemple était un exemple du passé qui n'aurait pas d'équivalent dans le présent, comme "Un fait sans exemple dans les annales judiciaires" (oui moi aussi je sais aller sur le site du larousse sauf que, contrairement à toi, je lis les choses) et n'était donc pas un exemple à suivre??? Remarque vu comme ton code sert à que dalle et que tu le juges toi-même comme contenant des données partielles, c'est effectivement le cas.

    Citation Envoyé par sambia39 Voir le message
    ...et ta calvitie ne t’aide pas
    Ma... "calvitie"??? Ok, si tu n'as pas d'argument plus pertinent à me soumettre qu'une hypothétique chute de cheveux (ouais, je sais, je dois probablement être "hors context" )
    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

  19. #19
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 191
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 191
    Points : 40 757
    Points
    40 757
    Par défaut
    @Sve@r: Pour le coup du (void), ce n'est pas la première fois que je vois ça, et le composant qu'il te manque pour comprendre, c'est le composant compilo/analyseur statique.
    En gros,
    1. Tu pars de l'école de pensée "Il faut toujours* tester le retour des fonctions en C, sinon on court à la catastrophe en cas d'erreur non-détectée."
      *Mais il y a des exceptions.
    2. Tu rajoutes une vérification à cet effet dans ta toolchain, histoire d'avoir un avertissement quand tu oublies de vérifier le retour.
    3. Maintenant, dans les cas exceptionnels où tu ne veux pas faire la vérification (genre: des printf(), dont la réussite ou l'échec n'affecte pas la suite de l'exécution), tu castes le retour en (void) pour dire explicitement à l'outil que la non-vérification est volontaire et délibérée.


    PS:
    Citation Envoyé par sambia39 Voir le message
    Ai-je écrit avec un pot de peinture ?
    Oui! Il y a des balises COLOR explicites partout dans ton texte!
    Ça sent le copier-coller vers l'éditeur "riche".
    Edit: Apparemment, ça a été corrigé depuis.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  20. #20
    Membre chevronné
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    mai 2010
    Messages
    523
    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 : 523
    Points : 1 870
    Points
    1 870
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Non, désolé, non, si char buff[]="babidy" alors strlen(buff) ne peut pas valoir zéro. J'ai beau le tourner dans tous les contextes du monde, je ne vois pas comment strlen(buff) peut valoir 0. Ou alors... ou alors c'est si tu écris plus tard char buff[]=""? Ce serait ça ton "garde-fou"??? Alors là les bras m'en tombent. Tu es vraiment en train de dire à la communauté des devs du C "hey les gars, si vous programmez comme des débiles j'ai la solution"??? Ou alors c'est pour math25 qui débute que tu as pondu cette... bouse? Pour lui dire "hey mon gars, tu débutes tu risques de faire des erreurs mais t'inquiète pas, voici un test qui va te protéger"? Et que se passera-t-il s'il suit tes conseils et qu'il écrit (comme dans ton post précédent) char buff[50]="babidy"??? 50 caractères offerts mais seulement 6 à pouvoir être saisis!!! Sans déconner t'es un vrai danger public du C toi!!!

    Désolé mais même comme ça, ton code sert à que dalle. Parce que même si on ne teste pas size_buff == 0, le fgets() suivant, lui, empêchera la saisie, pour peu qu'on l'écrive correctement. Car c'est fgets(buff, size_buff+1, stdin) qu'il faut écrire (hé oui, fgets() enlève systématiquement 1 à la taille qu'on lui donne pour pouvoir y stocker le '\0').

    Donc si on réécrit ton code ainsi...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main(void ){
     
        char buff[] = "babidy";
        size_t size_buff = strlen(buff);
     
        (void)fgets(buff, size_buff + 1, stdin);
        return EXIT_SUCCESS;
    }
    Ok. Mon garde-fou ne sert donc, absolument à rien . Ton fgets est sans UB; même écrit comme ceci: : (void)fgets(buff, size_buff + 1, stdin) avec un char buff[]=""
    Citation Envoyé par Sve@r Voir le message
    ... il fonctionnera absolument sans UB, y compris si on écrit ensuite char buff[] = "". Je ne dis pas que dans ce cas il produira le résultat escompté mais au-moins on ne sera pas dans le UB que ton test était censé (si j'en crois ton premier post) protéger car fgets() limitera elle-même la saisie pour ne pas dépasser.
    Bien la preuve que ton "garde-fou" sert à que dalle. Ou plutôt si, il te sert probablement à toi seul car tu dois être le seul à te penser assez con pour écrire un jour char buff[]="" et à te demander comment t'en protéger.
    Donc; si j'ai bien lu ce que tu as écrit tu ajoutes +1 à la taille du tampon à fgets et cela fonctionnera / fonctionne sans UB ?

    Vue d'ici et je dois encore être, le seul de nous deux à remarquer tes ambiguïtés de taille tampon, car avec un +1 à size_buff en a un très beau; ... mais très beau UB.Aussi je dois probablement être le seul de nous deux a comprendre qu'il ne faut pas indexer un buffer au-delà de sa taille ?

    Au début mon tout premier post je parlais d'avoir un garde-fou pour éviter un débordement ou pire UB en quoi ton UB pourrais également évité un off by one ? bien entendu, tu as raison pas d'Ub tout va bien ?


    Citation Envoyé par Médinoc Voir le message
    PS: Oui! Il y a des balises COLOR explicites partout dans ton texte!
    Ça sent le copier-coller vers l'éditeur "riche".
    @Médinoc: OK ; vous avez au moins l’amabilité de dire autrement.
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

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