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 :

Les chaines de caract�res en C [Tutoriel]


Sujet :

C

  1. #1
    R�dacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de donn�es
    Inscrit en
    Juin 2004
    Messages
    5 840
    D�tails du profil
    Informations personnelles :
    Sexe : Femme
    �ge : 42
    Localisation : France

    Informations professionnelles :
    Activit� : Administrateur de base de donn�es

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par d�faut Les chaines de caract�res en C
    http://nicolasj.developpez.com/articles/libc/string/

    Apr�s un rappel sur la structure des chaines de caract�res en C et un aper�u des fonctions de la biblioth�que standard servant � manipuler ces chaines, je vous propose de cr�er notre propre biblioth�que de manipulation des chaines de caract�res.
    Vous pouvez laisser un commentaire sur cet article � la suite.

  2. #2
    Expert �minent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retrait�
    Inscrit en
    D�cembre 2003
    Messages
    14 512
    D�tails du profil
    Informations personnelles :
    �ge : 69
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : Retrait�

    Informations forums :
    Inscription : D�cembre 2003
    Messages : 14 512
    Par d�faut
    Citation Envoy� par gege2061 Voir le message
    Les cha�nes de caract�res sont en fait stock�es dans un tableau de caract�res
    Il n'y a pas de 'caract�res'. C'est un tableau d'entiers de type char.

    "Les cha�nes de caract�res sont en fait stock�es dans un tableau de char"

    de code ASCII
    Il n'y a pas de 'code ASCII ' en C. une chaine est termin�e par un caract�re valant 0 (ou '\0' en octal ou '\x0' en hexad�cimal, si on aime la complication).

    Le fait qu'il ait la m�me valeur que le NUL du charset ASCII est un d�tail d'impl�mentation qui ne nous int�resse pas dans une th�orie g�n�rale sur le langage C.

    \0 n'existe pas en C. C'est '\0'.

    toute modification de la cha�ne s3 se conclura par une erreur de segmentation
    Non. �a se traduira par un comportement ind�termin�.

    Ca fait d�j� beaucoup d'impr�cisions... J'ai pas trop envie de continuer...

    Je propose :

    "<...> dont la fin est marqu�e par un caract�re nul, de valeur 0 et repr�sent� par le caract�re '\0' ou '\x0' ou la valeur 0 directement.

    Nota : le chiffre 0 (z�ro) est le caract�re '0'. Sa valeur d�pend du charset utilis� (en ASCII, 48 d�cimal)"

  3. #3
    R�dacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de donn�es
    Inscrit en
    Juin 2004
    Messages
    5 840
    D�tails du profil
    Informations personnelles :
    Sexe : Femme
    �ge : 42
    Localisation : France

    Informations professionnelles :
    Activit� : Administrateur de base de donn�es

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par d�faut
    Corrig� selon tes conseils.


  4. #4
    Expert �minent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retrait�
    Inscrit en
    D�cembre 2003
    Messages
    14 512
    D�tails du profil
    Informations personnelles :
    �ge : 69
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : Retrait�

    Informations forums :
    Inscription : D�cembre 2003
    Messages : 14 512
    Par d�faut
    Citation Envoy� par gege2061 Voir le message
    Corrig� selon tes conseils.

    OK.
    II-N. strtok
    Tu parles de 'ct', mais le param�tre est 't'...

    III-A. Modifier la case d'une cha�ne de caract�re
    ces fonctions retournant un espace allou�, j'aurais mis un suffixe _dyn ...

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    char *str_tolower_dyn (char const *s);
    char *str_toupper_dyn (char const *s)
    ;

    ou un rappel � strdup() ...

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    char *str_dup_tolower (char const *s);
    char *str_dup_toupper (char const *s);
    avec un rappel � 'free()'...

    j'aurais aussi pr�vu le cas plus simple de la chaine modifiable :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    char *str_tolower (char *s);
    char *str_toupper (char *s);

  5. #5
    Membre �m�rite
    Avatar de ol9245
    Homme Profil pro
    Chercheur
    Inscrit en
    Avril 2007
    Messages
    985
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 64
    Localisation : France, H�rault (Languedoc Roussillon)

    Informations professionnelles :
    Activit� : Chercheur

    Informations forums :
    Inscription : Avril 2007
    Messages : 985
    Billets dans le blog
    1
    Par d�faut des mallocs � l'int�rieur d'une fonction : est-ce bien raisonnable ?
    Bonjour,

    Je passais par ici par hasard. Je vois bien que l'exemple date un peu...
    Une remarque sur les exemples de code donn�s, comme par exemple celui-ci :
    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
    char *str_tolower (const char *ct)
    {
       char *s = NULL;
    
       if (ct != NULL)
       {
          int i;
          s = malloc (sizeof (*s) * (strlen (ct) + 1));
          if (s != NULL)
          {
             for (i = 0; ct[i]; i++)
             {
                s[i] = tolower (ct[i]);
             }
             s[i] = '\0';
          }
       }
       return s;
    }
    Je crois que c'est une mauvaise id�e de montrer � des d�butants des exemples de fonctions structur�es comme celle-ci. Une fonction est responsable de l'utilisation qu'elle fait de la m�moire. Donc si une fonction alloue de la m�mooire avec un malloc, elle doit la lib�rer avec un free abant de sortir.

    En cons�quence, une fonction comme celle-ci ne peut pas renvoyer son r�sultat sous forme d'une chaine de caract�re qu'elle a allou�e sur le tas. C'est une mauvaise pratique. La responsabilit� d'allouer de la m�moire revient � l'appellant de la fonction, pas � la fonction elle-m�me.

    La solution la plus simple est de faire la modification sur la chaine en place. Sil l'appelant veut garder l'original, libre � lui de faire une copie avant :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    void to_upper(char *c)
    {
    	for (; *c; ++c)
    		if (*c >= 'a' && *c <= 'z')
    			*c += 'A' - 'a';
    }
    Une autre solution, pas tr�s satisfaisante, est de prendre deux arguments, l'un en entr�e, l'autre en sortie. Un peu moche.
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    void to_upper(const char *in, char *out)
    {
    	for (; *in; ++in, ++out)
    		*out = *in + (*in >= 'a' && *in <= 'z' ? 'A' - 'a' : 0);
    }
    Voil�. C'est juste mon grain de sel...

  6. #6
    Expert �minent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retrait�
    Inscrit en
    D�cembre 2003
    Messages
    14 512
    D�tails du profil
    Informations personnelles :
    �ge : 69
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : Retrait�

    Informations forums :
    Inscription : D�cembre 2003
    Messages : 14 512
    Par d�faut
    Citation Envoy� par ol9245 Voir le message
    Bonjour,

    Je passais par ici par hasard. Je vois bien que l'exemple date un peu...
    Une remarque sur les exemples de code donn�s, comme par exemple celui-ci :
    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
    char *str_tolower (const char *ct)
    {
       char *s = NULL;
    
       if (ct != NULL)
       {
          int i;
          s = malloc (sizeof (*s) * (strlen (ct) + 1));
          if (s != NULL)
          {
             for (i = 0; ct[i]; i++)
             {
                s[i] = tolower (ct[i]);
             }
             s[i] = '\0';
          }
       }
       return s;
    }
    Je crois que c'est une mauvaise id�e de montrer � des d�butants des exemples de fonctions structur�es comme celle-ci. Une fonction est responsable de l'utilisation qu'elle fait de la m�moire.
    Comme malloc() ? Ou fopen () ?

    J'ai bien insist� que le fait que la fonction allouait un bloc et qu'il fallait le lib�rer apr�s usage. C'est la seule fa�on de faire des copies de chaines r�entrantes, ce qui permet le multi-t�che ...

    Donc si une fonction alloue de la m�moire avec un malloc, elle doit la lib�rer avec un free avant de sortir.
    Dans ce cas, une variable locale devrait suffire ...

    En cons�quence, une fonction comme celle-ci ne peut pas renvoyer son r�sultat sous forme d'une chaine de caract�re qu'elle a allou�e sur le tas. C'est une mauvaise pratique. La responsabilit� d'allouer de la m�moire revient � l�appelant de la fonction, pas � la fonction elle-m�me.
    Voil� une position bien dogmatique. Il faudra en parler � celui qui a �crit fopen() ...

    Dans la pratique �videmment qu'on passe son temps � allouer ici et � lib�rer l�. Certes �a demande quelques efforts de programmation et des outils de v�rification (j'ai m�me fini par en �crire un, voir ma biblioth�que CLIB), mais c'est le seul moyen d'�tre efficace et de ne pas passer son temps � recopier des donn�es qui peuvent parfois �tre longues ...

    M�me si tu utilises un syst�me plus sym�trique qui ressemble � de la programmation objet (ADT), il y a quand m�me un fonction de cr�ation de l'objet et une fonction de destruction de celui-ci. Le fait que l'on contr�le manuellement la destruction permet de cr�er des objet dynamiques persistants (le temps de leur utilisation et dans n'importe quel t�che).

    Sur ce, moi je suis musicien, maintenant, alors ces probl�mes l�, je m'en tape un peu, l� ...

  7. #7
    Nouveau candidat au Club
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Janvier 2017
    Messages
    2
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Janvier 2017
    Messages : 2
    Par d�faut
    Dans ce cas, une variable locale devrait suffire ...
    Bonjour, � ma connaissance, contrairement aux langages disposant d'un syst�me de "garbage collector", la m�moire allou�e par malloc a besoin d'�tre lib�r�e avant la perte de sa r�f�rence, en l'occurrence, la variable locale contenant l'adresse de cette m�moire... sinon c'est la fuite (en avant) de m�moire assur�e.
    En C: 1 malloc => 1 free

  8. #8
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 515
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyr�n�es)

    Informations professionnelles :
    Activit� : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 515
    Par d�faut
    den75,
    Quand ol9245 a �nonc� la r�gle g�n�rale :
    si une fonction alloue de la m�mooire avec un malloc, elle doit la lib�rer avec un free abant de sortir
    et que Emmanuel Delahaye avait r�pondu :
    Dans ce cas, une variable locale devrait suffire
    il ne proposait pas d'appeler malloc sans appeler free, mais d'allouer une variable automatique, qui sera donc automatiquement d�sallou�e quand on sortira de la port�e de cette variable.

    Cependant, quand la taille � allouer est inconnue � la compilation, il vaut souvent mieux allouer avec malloc que d'allouer un VLA (Variable Length Array) ou d'appeler une fonction non standard comme alloca.

    A part �a, de mon c�t�, je ne suis pas toujours contre les fonctions qui appellent malloc et demandent � l'utilisateur de la fonction d'appeler eux-m�me free. Mais, pour �viter les fuites m�moires, il faut utiliser une convention. Par exemple, j'aime bien le suffixe "_dyn" propos� par Emmanuel Delahaye.

    Par contre, pour une fonction qui convertit une cha�ne en minuscules, je n'aurais pas fait d'allocation dans le tas. J'aurais fait comme �a :
    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
    #include <ctype.h>
    #include <stdio.h>
     
    void MyProject_str_to_tolower(char* restrict dest, const char* restrict src)
    {
    	for(; *src != '\0'; ++src, ++dest)
    		*dest = tolower(*src);
    	*dest = '\0';
    }
     
    int main()
    {
    	const char src[] = "Hello world!";
    	char dest[sizeof(src)]; // L'utilisateur est libre d'allouer la chaîne résultante dans la pile.
    	MyProject_str_to_tolower(dest, src);
    	printf("%s", dest);
    	return 0;
    }
    C'est proche de ce la solution que ol9245 avait qualifi�e de moche, mais je ne trouve pas �a moche.

    Edit 2017-01-25-17h27 : Conversion en majuscules remplac�e par une conversion en minuscules pour mieux coller aux pr�c�dents messages du fil.

  9. #9
    Membre tr�s actif
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    551
    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 : 551
    Par d�faut
    Bonsoir, La discussion date cependant je peut-�tre apport� quelque pr�cision sans trop lanc� de d�bats.
    Citation Envoy� par Emmanuel Delahaye Voir le message

    Non. �a se traduira par un comportement ind�termin�.
    Je pense qu'il n'y a pas de comportement ind�termin� en soi, mais il y a bien un segment d�faut justifier .
    Je m�explique. Ici s3 const char *s3 = "D�veloppez"; est un pointeur constant sur une cha�ne constante. Lors de la phase de compilation toute modification sur s3 sera interdite et la compilation �chouera, car l�erreur a �t� d�cel�, mais dans le cas contraire "char *s3 = "D�veloppez" le compilateur placera la cha�ne constante dans un segment de donn�es en lecture seule et toute tentative de modification � travers ce pointeur aboutira syst�matiquement � une erreur de segmentation donc pour une variable pointeur sur une cha�ne constante on aura syst�matiquement une erreur de segmentation et non un comportement ind�termin�.

    Cas compilation avec const
    Code C : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #include <stdio.h>
    #include <stdlib.h>
     
    int main( void ){
     
        const char *ptr = "Bonjour";
        ptr[2] = 'Z';                     
        return EXIT_SUCCESS;
    }
    Code Gcc : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    root@mv:~# gcc *.c -Wall -Werror -g -o Deb 
    source.c: In function 'main':
    source.c:7:9: error: assignment of read-only location '*(ptr + 2u)'
      ptr[2] = 'Z';

    Cas compilation sans const
    Code C : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <stdio.h>
    #include <stdlib.h>
    
    int main( void ){
        
        char *ptr = "Bonjour";
        ptr[2] = 'Z';                     <<< Thread 1: address access protected (fault address: 0x400566)
        return EXIT_SUCCESS;
    }

    Code Gcc : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
     
    root@mv:~# gcc *.c -Wall -Werror -g -o Deb 
    root@mv:~# ./Deb 
    Segmentation fault


    � bient�t.

  10. #10
    Nouveau candidat au Club
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Janvier 2017
    Messages
    2
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Janvier 2017
    Messages : 2
    Par d�faut
    il ne proposait pas d'appeler malloc sans appeler free, mais d'allouer une variable automatique, qui sera donc automatiquement d�sallou�e quand on sortira de la port�e de cette variable.
    Oui, bien s�r. J'avais mal lu et le code de d�part et les commentaires.
    Maintenant concernant le choix entre:

    M�thode 1:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    void Appelant()
    {
    char src[]="Hello";
    char dst[LENGTH];
     
    StrManip(src,dst);
    ...
    }
    ou

    M�thode 2:
    void Appelant()
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    {
    char src[]="Hello";
    char *dst=StrManip(src);
    ...
    free(dst);
    ...
    }
    Je pense que si LENGTH est pr�dictible voire simplement born�e alors il faut choisir la M�thode 1
    Mais dans le cas o� la taille m�moire demand�e pour le r�sultat est "trop variable" alors la M�thode 2 peut faire sens.

  11. #11
    Mod�rateur

    Avatar de Bktero
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 498
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 498
    Billets dans le blog
    1
    Par d�faut
    Citation Envoy� par sambia39 Voir le message
    Je pense qu'il n'y a pas de comportement ind�termin� en soi, mais il y a bien un segment d�faut justifier .
    [...]
    mais dans le cas contraire "char *s3 = "D�veloppez" le compilateur placera la cha�ne constante dans un segment de donn�es en lecture seule et toute tentative de modification � travers ce pointeur aboutira syst�matiquement � une erreur de segmentation donc pour une variable pointeur sur une cha�ne constante on aura syst�matiquement une erreur de segmentation et non un comportement ind�termin�.
    C'est bien un comportement ind�termin� https://www.securecoding.cert.org/co...+qualification

    Il n'y a pas obligatoirement d'erreur de segmentation. Par exemple, j'ai constat� que sur certains MCU, si tu essayes d'�crire � une adresse qui pointe vers de la m�moire flash, �a n'a juste pas d'effet.

  12. #12
    Expert confirm�

    Avatar de fearyourself
    Homme Profil pro
    Ing�nieur Informaticien Senior
    Inscrit en
    D�cembre 2005
    Messages
    5 121
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activit� : Ing�nieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : D�cembre 2005
    Messages : 5 121
    Par d�faut
    Citation Envoy� par sambia39 Voir le message
    mais dans le cas contraire "char *s3 = "D�veloppez" le compilateur placera la cha�ne constante dans un segment de donn�es en lecture seule
    Je pense que ceci n'est pas vrai. Je ne vois nul part dans la norme du langage qu'une cha�ne d�finie par char* doit se trouver en m�moire en lecture seule. Je sais que c'est souvent ce qui se passe et pour r�soudre le souci, on fait souvent char s3[] = "D�veloppez" si on veut modifier la cha�ne mais je ne suis pas s�r que la norme le force vu que le C est utilis� sur des architectures qui n'ont pas de section lecture seule.

    Mais j'ai un doute donc je pose la question Si j'ai raison, alors il vaut mieux dire "souvent" que toujours.

  13. #13
    Expert �minent

    Femme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    D�tails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (�le de France)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par d�faut
    Concr�tement, ce n'est pas char* qui peut y �tre plac�e, ca c'est une variable sans importance pour la question.
    C'est la chaine lit�rale. Et encore, la norme ne l'impose pas. Je crois qu'elle n'impose m�me pas l'existence d'une m�moire d�di�e � ce type d'objet.
    Elle pourrait tout aussi bien �tre dans le tas, ou en bas de la pile.

  14. #14
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activit� : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par d�faut
    La norme pr�cise qu'il s'agit d'un UB si on tente de modifier les cha�nes litt�rales. Ce qui est requis est qu'une telle cha�ne soit stock�e dans un tableau statique de la bonne longueur (pas plus, pas moins) → norme C11 6.4.5 String literals.

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    char *ptr="hello world"; // ptr pointe sur le premier caractère du littéral
    *ptr='H'; // UB !
     
    char arr[]="hello world"; // on copie le littéral dans le tableau
    arr[0]='H'; // OK
    Dans le code pr�c�dent, la norme n'oblige en rien � avoir le litt�ral "hello world" en read only, ni m�me � n'avoir qu'une version de ce litt�ral ni m�me plusieurs.
    Le fait est qu'une optimisation courante est d'avoir des cha�nes litt�rales en read only (plus contraignant qu'un const) simplement pour pouvoir gagner de la place et fusionner plusieurs cha�nes dans un m�me tableau. gcc proposait un option il y a quelques ann�es pour �rendre� ces cha�nes �crivables (?) mais cette option a �t� enlev�e. La tendance est de forcer une plus grande const correctness→-Wwrite-strings (pour autant que ce soit utile et coh�rent en C). Du coup on voit souvent :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    const char *ptr="hello world";
    // à la place de
    char *ptr="hello world";

  15. #15
    Expert confirm�

    Avatar de fearyourself
    Homme Profil pro
    Ing�nieur Informaticien Senior
    Inscrit en
    D�cembre 2005
    Messages
    5 121
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activit� : Ing�nieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : D�cembre 2005
    Messages : 5 121
    Par d�faut
    picodev

  16. #16
    Membre tr�s actif
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    551
    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 : 551
    Par d�faut
    Bonsoir,

    Citation Envoy� par Bktero Voir le message
    C'est bien un comportement ind�termin� https://www.securecoding.cert.org/co...+qualification.....
    Citation Envoy� par fearyourself Voir le message
    Je pense que ceci n'est pas vrai. Je ne vois nul part dans la norme du langage qu'une cha�ne d�finie par char* doit se trouver en m�moire en lecture seule. Je sais que c'est souvent ce qui se passe et pour r�soudre le souci, on fait souvent char s3[] = "D�veloppez" si on veut modifier la cha�ne mais je ne suis pas s�r que la norme le force vu que le C est utilis� sur des architectures qui n'ont pas de section lecture seule.

    Mais j'ai un doute donc je pose la question Si j'ai raison, alors il vaut mieux dire "souvent" que toujours.
    J�ai �crit que cela n�est pas un comportement ind�termin� � cause de ce qui se trouve sous le capot.
    Alors comment se pr�sentent les choses : dans un premier temps on va d�compiler l�ex�cutable afin de d�terminer o� est-ce que notre variable pointeur sur cha�ne constante se trouve-t-il, mais �galement savoir si le segment m�moire ou se trouve cette variable peut-�tre lue et modifi�e

    Code objdump -Sr source.o && readelf -l Deb : 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
    root@mv:~# objdump -Sr source.o && readelf -l Deb
    
    source.o:     file format elf64-x86-64
    
    
    Disassembly of section .text:
    
    0000000000000000 <main>:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main( void ){
       0:	55                   	push   %rbp
       1:	48 89 e5             	mov    %rsp,%rbp
    
    	char *ptr = "DEBUG_TEST";
       4:	48 c7 45 f8 00 00 00 	movq   $0x0,-0x8(%rbp)
       b:	00 
    			8: R_X86_64_32S	.rodata
    	*(ptr) = 'A';
       c:	48 8b 45 f8          	mov    -0x8(%rbp),%rax
      10:	c6 00 41             	movb   $0x41,(%rax)
    	return EXIT_SUCCESS;
      13:	b8 00 00 00 00       	mov    $0x0,%eax
    }
      18:	5d                   	pop    %rbp
      19:	c3                   	retq   
    
    Elf file type is EXEC (Executable file)
    Entry point 0x4003c0
    There are 8 program headers, starting at offset 64
    
    Program Headers:
      Type           Offset             VirtAddr           PhysAddr
                     FileSiz            MemSiz              Flags  Align
      PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                     0x00000000000001c0 0x00000000000001c0  R E    8
      INTERP         0x0000000000000200 0x0000000000400200 0x0000000000400200
                     0x000000000000001c 0x000000000000001c  R      1
          [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
      LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                     0x000000000000068c 0x000000000000068c  R E    200000
      LOAD           0x0000000000000690 0x0000000000600690 0x0000000000600690
                     0x0000000000000228 0x0000000000000230  RW     200000
      DYNAMIC        0x00000000000006a8 0x00000000006006a8 0x00000000006006a8
                     0x00000000000001d0 0x00000000000001d0  RW     8
      NOTE           0x000000000000021c 0x000000000040021c 0x000000000040021c
                     0x0000000000000044 0x0000000000000044  R      4
      GNU_EH_FRAME   0x0000000000000560 0x0000000000400560 0x0000000000400560
                     0x0000000000000034 0x0000000000000034  R      4
      GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                     0x0000000000000000 0x0000000000000000  RW     10
    
     Section to Segment mapping:
      Segment Sections...
       00     
       01     .interp 
       02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 
       03     .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 
       04     .dynamic 
       05     .note.ABI-tag .note.gnu.build-id 
       06     .eh_frame_hdr 
       07     
    root@mv:~#

    Observerez ci-dessus que la cha�ne constante a �t� placer dans (mon cas) dans .RODATA. ( Read-Only Data) en clair donn� constant en lecture seule. Qui est une zone distingu�e du segment de donn�es "si je peux dire ainsi" On distingue �galement que cette zone permet la lecture et l�ex�cution, mais pas l��criture donc essayer de modifier l��l�ment qui se trouve dans cette zone d�bouche syst�matiquement sur une erreur de segmentation (sous UNIX tout comme GNU/LINUX et Mac Os); ce qui justifie le segment d�faut et que nous n�avons pas affaire � un comportement ind�termin�, mais bien une erreur de segmentation par ce que l�on a voulu �crire dans une zone qui ne nous est pas autoris�e.

    Pour ce qui est de UB @picodev a bien expliquer l� choses
    � bient�t@

  17. #17
    Expert confirm�

    Avatar de fearyourself
    Homme Profil pro
    Ing�nieur Informaticien Senior
    Inscrit en
    D�cembre 2005
    Messages
    5 121
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activit� : Ing�nieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : D�cembre 2005
    Messages : 5 121
    Par d�faut
    Histoire qu'on soit clair: je discutais juste du fait que la phrase disait : le compilateur place les char *s = "blah" dans une zone lecture seule. Et je voulais juste faire noter que cela n'est pas toujours le cas.

    Dans 99% des syst�mes, ce que tu as dit est vrai

Discussions similaires

  1. question sur les chaine de caract�res
    Par amy0o0 dans le forum C
    R�ponses: 11
    Dernier message: 14/10/2006, 14h14
  2. [CR 10] Traitement sur les chaines de caract�res
    Par sylviefrfr dans le forum SAP Crystal Reports
    R�ponses: 1
    Dernier message: 11/09/2006, 09h16
  3. question sur les chaines de caract�res
    Par pierrOPSG dans le forum C
    R�ponses: 5
    Dernier message: 13/04/2006, 18h55
  4. les chaines de caract�res
    Par mrtatou dans le forum C
    R�ponses: 4
    Dernier message: 25/01/2006, 14h18
  5. xsl : test sur les chaine de caract�re
    Par yos dans le forum XSL/XSLT/XPATH
    R�ponses: 1
    Dernier message: 13/07/2005, 15h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter