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 :

[const]Différence comportement C/C++


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Ingénieur consultant
    Inscrit en
    Novembre 2004
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur consultant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 64
    Points : 88
    Points
    88
    Par défaut [const]Différence comportement C/C++
    Quelqu'un arrive-t-il à expliquer le comportement ce code un fois compilé (avec g++) puis exécuter:

    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
     
    int main()
    {
    	const int a = 2;
    	int * pa;
    	const int * cpa;
     
    	cpa = &a;
    	pa = (int*)cpa; //Pour gruger le mot clé const
    	*pa = 4;
     
    	printf("a = %d\n", a);
    	printf("*pa = %d\n", *pa);
     
    	return 0;
    }
    On a alors la sortie suivante :

    a = 2
    *pa = 4

    Pourquoi n'a-t-on pas :

    a = 4
    *pa = 4

    pa est censé pointé le contenu de a ?
    c'est d'ailleurs le résultat obtenu avec gcc...

  2. #2
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Tu veus encore plus étonnant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    const int ca = 0;
    int& ra = const_cast<int&>(ca);
    ++ra;
    std::cout << ra << ca;
    std::cout << &ra << &ca;
    Les objets sont à la même adresse mais n'ont pas la même valeur !
    Je suis pas certain (pas réussi à vérifier dans la norme), mais je crois que quand tu définis une variable constante sur un type fondamentale alors la valeur est imuable quoique tu fasses. (comment je sais pas, soit il remplace de manière litéral mais j'en doute, soit il stoocke la variable dans une table innaccesible et l'utilise dès qu'il voit la variable nue, ie ca).

  3. #3
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Salut

    Si tu regardes le code assemblé (avec visual studio) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    	printf("a = %d\n", a);
    004113DA  mov         esi,esp 
    004113DC  push        2    
    004113DE  push        offset string "a = %d\n" (41580Ch)
    Là ou a est utilisé, le compilo met directement en dur la valeur que tu lui a donné à son initialisation. C'est très bien d'ailleurs, car c'est mal de vouloir gruger const
    Find me on github

  4. #4
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    C'est pas un comportement indéfini de vouloir modifier la valeur d'une constante manifeste ?

  5. #5
    Membre régulier
    Profil pro
    Ingénieur consultant
    Inscrit en
    Novembre 2004
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur consultant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 64
    Points : 88
    Points
    88
    Par défaut
    Je ne pense pas que cela soit en rapport avec la norme, mais plutôt dû à des optimisations de compilateur.

    Si je compile avec gcc sans optimisation (-O0 ou rien) j'ai le résultat attendu :

    4
    4

    si j'utilise gcc avec optimisation (-O1,2,3...) j'ai la même chose qu'avec g++ :

    2
    4

    Par contre ce qui me dérange avec g++ c'est que sans options d'optimisation (-O0 ou rien par défault) on devrait avoir :

    4
    4

    or ce n'est pas le cas, que l'on utilise -O0,1,2,3... ou rien on a toujours le même résultat

  6. #6
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par jldgbu Voir le message
    Je ne pense pas que cela soit en rapport avec la norme, mais plutôt dû à des optimisations de compilateur.
    Si ça a à voir car à partir du moment ou tu es dans un comportement indéfini, le compilateur a le droit de faire ce qui lui plaît, il ne te doit strictement rien. Donc ça varie d'un compilo à un autre, c'est logique et ça ne devrais pas te poser de souci car dans un code propre, on ne modifie pas des const .
    Find me on github

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    Par défaut
    T'as joué au plus malin avec le compilateur et t'as perdu.

  8. #8
    Membre régulier
    Profil pro
    Ingénieur consultant
    Inscrit en
    Novembre 2004
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur consultant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 64
    Points : 88
    Points
    88
    Par défaut
    T'as joué au plus malin avec le compilateur et t'as perdu.
    Mon problème n'est pas de jouer au plus malin avec un compilateur mais de m'assurer que personne ne peut changer une variable const que j'exposerai par quelques bidouilles que ce soit...

  9. #9
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par jldgbu Voir le message
    Mon problème n'est pas de jouer au plus malin avec un compilateur mais de m'assurer que personne ne peut changer une variable const que j'exposerai par quelques bidouilles que ce soit...
    Si t'as des programmeurs qui bricolent pour modifier tes const, c'est qu'il y a un problème autre à mon avis, qui tient à l'organisation et aux règles de codage à respecter.

    En plus tu vois qu'avec g++, on a bien le comportement de const non modifié, donc aucun souci si tu utilises g++ non ?
    Find me on github

  10. #10
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par jldgbu Voir le message
    Mon problème n'est pas de jouer au plus malin avec un compilateur mais de m'assurer que personne ne peut changer une variable const que j'exposerai par quelques bidouilles que ce soit...
    La philosophie de C++, c'est plutôt "protect agains murphy, not machiavel". const suit cette philosophie.

    Si tu veux vraiment t'assurer que personne ne modifie une variable const que tu exposes, le meilleur moyen que je vois est d'en renvoyer une copie à chaque fois, et de ne pas exposer la source. Mais même ça, ça se contourne.

  11. #11
    Membre régulier
    Profil pro
    Ingénieur consultant
    Inscrit en
    Novembre 2004
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur consultant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 64
    Points : 88
    Points
    88
    Par défaut
    Si tu veux vraiment t'assurer que personne ne modifie une variable const que tu exposes, le meilleur moyen que je vois est d'en renvoyer une copie à chaque fois, et de ne pas exposer la source. Mais même ça, ça se contourne.
    ? Je suis curieux t'as un exemple de code ?

  12. #12
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     MonTruc truc() { return m_truc; } // copie, pas d'accès a direct a truc

  13. #13
    Membre régulier
    Profil pro
    Ingénieur consultant
    Inscrit en
    Novembre 2004
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur consultant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 64
    Points : 88
    Points
    88
    Par défaut
    Euh c'était pas ça ma question, je sais comment renvoyer une copie pour ne pas exposer la source mais plutôt un exemple qui montre comment contourner ça.

  14. #14
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Après quelques tests, on peut se rendre compte que la norme C99 et c++ doivent être différentes a propos des const :

    Le programme suivant compile (avec gcc) avec un seul warning alors que avec g++, il donne une erreur.
    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
     
    #include <stdlib.h>
    #include <stdio.h>
     
    const char*prouver_const(const char* chn)
    {
        char*chn2=chn;
        chn2[0]='T';
        return chn;
    }
     
     
    int main()
    {
        char*chn=malloc(6);
        strcpy(chn,"tests");
        printf("%s",prouver_const(chn));
     
    }
    De plus, le programme suivant lui, affiche "bug" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdlib.h>
    #include <stdio.h>
     
     
    int main()
    {
        char *chn="test";//L'allocation est automatique si c'est à la déclaration je crois.
        printf("%s",chn);
        chn=realloc(chn,6);
        if(!chn)
            printf("bug");
    }
    Quelqu'un pourrait-il l'expliquer ?

  15. #15
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    De plus, le programme suivant lui, affiche "bug" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdlib.h>
    #include <stdio.h>
     
     
    int main()
    {
        char *chn="test";//L'allocation est automatique si c'est à la déclaration je crois.
        printf("%s",chn);
        chn=realloc(chn,6);
        if(!chn)
            printf("bug");
    }
    Quelqu'un pourrait-il l'expliquer ?
    Il n'y a pas d'allocation automatique. Tu crées juste un pointeur que tu l'initialise avec l'adresse du chaîne constante.

    chn contenant l'adresse d'une chaîne constante et non une adresse retourné par malloc() (ou équivalent) ni NULL, l'appel à realloc() est un comportement indéfini :

    Otherwise, if ptr does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to the free or realloc function, the behavior is undefined.
    Au passage, en C++ il n'est pas recommandé d'utiliser malloc(), realloc() et compagnie.

    Et il est assez vain d'essayer de comprendre, d'expliquer ou de prédire un comportement indéfinie. Une implémentation est en droit de faire ce qu'elle veut et pas nécessairement toujours la même chose (cela peut varier notamment en fonction du niveau d'optimisation).

  16. #16
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    Par défaut
    Et une personne malveillant n'est pas obligée d'utiliser vos en-têtes, ni même vos méthodes ou fonctions pour aller fouiller dans vos données, ni même d'utiliser du code C++.

  17. #17
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par jldgbu Voir le message
    Euh c'était pas ça ma question, je sais comment renvoyer une copie pour ne pas exposer la source mais plutôt un exemple qui montre comment contourner ça.
    Pas d'exemple simple, d'autant que ce n'est pas le genre de choses auxquelles je m'amuse. Je sais que c'est possible en C++ (logique), mais pas en .Net (code managé). En gros, l'idée de base, c'est que rien ne t'empêche d'écrire à une adresse mémoire qui t'appartient, du moment que la page est inscriptible. Donc si la valeur est alloué à l'exécution (ie, pas dans la zone data du programme), le programme peut la modifier.

    Après, la difficulté principale réside dans le fait de trouver l'adresse où écrire. Mais ce n'est pas insurmontable. Il faut bien réaliser, quand on fait du développement, que les fonctionnalités telles que const, private, etc, sont des fonctionnalités de vérification statique, et aucunement de sécurité.

  18. #18
    Membre régulier
    Profil pro
    Ingénieur consultant
    Inscrit en
    Novembre 2004
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur consultant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 64
    Points : 88
    Points
    88
    Par défaut
    Pour noIdea

    Le deuxième programme s'explique bien par le fait qu'un realloc est fait sur des données non allouées par malloc.

    Pour le premier programme :

    On ne peut pas normalement affecter une valeur de pointeur constant à un pointeur non constant, sauf pour les chaines de caractères qui font exception.

    Une chaine du type

    "Hello"

    est une chaine de caractères constantes, on ne devrait donc pouvoir affecter son addresse qu'à un pointeur de caractères constant.

    const char* chaine = "hello"; //plus rigoureux

    Seulement en C on a pris l'habitude suivante:

    char* chaine = "hello";

    Donc par compatibilité on a la conversion implicite entre "const char *" et "char *"

    Par contre si tu t'amuses à modifier la chaine de caractères constante tu pourras toujours compiler mais à l'execution là ce sera la roulette russe. Ca plantera ou pas selon que le compilateur choisit de mettre ça dans une zone mémoire ou tu peux écrire...

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Donc par compatibilité on a la conversion implicite entre "const char *" et "char *"
    Ou plus exactement en C, on a:
    • Conversion implicite entre "abc" et char*, pour cette histoire de compatibilité (sous gcc, on peut désactiver ça avec l'option -Wwrite-strings en ligne de commande).
    • Conversion implicite autorisée mais (le plus souvent) avec warning de X const* à X*, du au typage faible du C.
    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.

Discussions similaires

  1. Différence comportement Cassini/IIS
    Par Laotzu dans le forum ASP.NET
    Réponses: 1
    Dernier message: 18/01/2011, 10h17
  2. [EasyPHP] Différence comportement démarrage Apache par EasyPHP ou par ligne de commande
    Par SONY30 dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 6
    Dernier message: 19/10/2010, 11h48
  3. Différence comportement entre product et RCP
    Par DaveShot dans le forum Eclipse Platform
    Réponses: 2
    Dernier message: 16/03/2010, 09h03
  4. [swing]Différence de comportement selon hardware
    Par xxaragornxx dans le forum Composants
    Réponses: 13
    Dernier message: 16/11/2005, 17h51
  5. [JFrame] Explication sur une différence de comportement
    Par jems dans le forum Agents de placement/Fenêtres
    Réponses: 2
    Dernier message: 06/07/2005, 09h23

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