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 :

Utiliser la case mémoire après la fin d'une zone mémoire valide?


Sujet :

C

  1. #1
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut Utiliser la case mémoire après la fin d'une zone mémoire valide?
    Salut!

    La norme (98/99 chapitre 6.5.8 point 8) précise:
    If both the pointer
    operand and the result point to elements of the same array object, or one past the last
    element of the array object, the evaluation shall not produce an overflow; otherwise, the
    behavior is undefined. If the result points one past the last element of the array object, it
    shall not be used as the operand of a unary * operator that is evaluated.
    Cela signifie t'il que l'on peut utiliser sans risque l'élément suivant la fin du tableau pour faire des choses comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char s[10]="1234567890";
    s[10]='\0';
    Autrement dit est il garantie que cette case mémoire ne peut pas servir à stocker une autre variable ou cela signifie t'il juste que cette case ne pointe pas en dehors de la zone allouée au programme?

    Merci.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  2. #2
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut
    Ce que dit la norme, c'est que l'on peut calculer &s[10], cela afin de faciliter la comparaison de pointeurs. Mais il est hors de question d'acceder a s[10].
    Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    int tab_1[10];
    int tab_2[10];
     
    int *p_i1;
    int *p_i2 = tab_2;
    int *end = &tab_1[10]; /* legal, but element is non-existent */
     
    for(p_i1 = tab_1; p_i1 < end; p_i1++)
    {
      *p_i2++ = *p_i1;
    }

  3. #3
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Le code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     int i;
      char s[10] = "123456789";
      char t[] = "123456789";
     for(i=0;i<10;i++)
     {
      if (s[i]=='\0')
       fprintf(stderr, "\\0");
      else
       fprintf(stderr, "%c",s[i]);
     
     
     }
     
     fprintf(stderr, "\n");
     
      for(i=0;i<10;i++)
     {
      if (t[i]=='\0')
       fprintf(stderr, "\\0");
      else
       fprintf(stderr, "%c",t[i]);
     
     
     }
    Affiche chez moi :

    123456789\0
    123456789\0

    D'ailleurs, la chaîne "123456789" est bien de 10 éléments. Donc ça va.

    Par contre si on avait mis avec s[9].

    Comme ce code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
      int i;
      char s[9] = "123456789";
      char t[] = "123456789";
     for(i=0;i<10;i++)
     {
      if (s[i]=='\0')
       fprintf(stderr, "\\0");
      else
       fprintf(stderr, "%c",s[i]);
     
     
     }
     
     fprintf(stderr, "\n");
     
      for(i=0;i<10;i++)
     {
      if (t[i]=='\0')
       fprintf(stderr, "\\0");
      else
       fprintf(stderr, "%c",t[i]);
     
     
     }
    J'obtiens:

    123456789$
    123456789\0

    Et ici, ce n'est pas bon du tout de remplacer s[10].
    Je ne répondrai à aucune question technique en privé

  4. #4
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Citation Envoyé par DaZumba
    Ce que dit la norme, c'est que l'on peut calculer &s[10], cela afin de faciliter la comparaison de pointeurs. Mais il est hors de question d'acceder a s[10].
    D'accord.
    legal, but element is non-existent
    Tu veux dire dans le sens élément du tableau?

    En fait l'éxécution de code tel que:
    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<stdio.h>
    #include<stdlib.h>
     
    int main(void)
    {
          char s0[10]="chainech0";
          char s1[10]="chainech1";
          char s2[10]="chainech2";
          char s3[10]="chainech3";
          char s4[10]="chainech4";
     
          for(int i=0;i<60;i++){
          printf("s4[%d] : %c\n",i,s4[i]);
          }
     
          system("pause");
          return EXIT_SUCCESS;
    }
    Montre que l'espace entre les chaines est assez conséquent pour y stocker encore des caractères.
    Est-ce dépendant de l'implémentation ou garanti?
    Ces espaces seront ils toujours disponibles au sens où ils ne seront pas utilisés pour stocker d'autres données?
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  5. #5
    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
    Euh... Rien n'est garanti, là : Tu n'as que cinquante caractères, pas soixante...
    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.

  6. #6
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut
    Citation Envoyé par seriousme
    Tu veux dire dans le sens élément du tableau?
    Oui. Le 11ème élément n'existe pas. Par contre, son adresse (ou plutôt, l'adresse du 10ème élément incrémentée de 1) est garantie comme étant valide.

    Est-ce dépendant de l'implémentation ou garanti?
    Cela dépend du compilateur et comment il arrange la mémoire automatique. La règle est: on ne dépasse jamais les limites d'un tableau (0 à N-1 pour un tableau de dimension N).

  7. #7
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    seriousme :
    Montre que l'espace entre les chaines est assez conséquent pour y stocker encore des caractères.
    Est-ce dépendant de l'implémentation ou garanti?
    Le compilateur arrange les données dans l'ordre qu'il veut en tenant compte en plus des options d'alignement des données. Donc, rien n'est garanti
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Points : 542
    Points
    542
    Par défaut
    Si ce n'est pas explicitement documenté, ni dans la norme, ni dans aucune doc de compilateur, alors ça ne doit pas être fait (B-A-BA de la programmation; ce genre de trucs c'était bon du temps du C64 et de l'Oric, mais les choses ont [heureusement] évolué depuis !).
    "La forme même des Pyramides prouve que de tous temps, les ouvriers n'ont jamais pensé qu'à en faire de moins en moins."

    G. CLEMENCEAU

  9. #9
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    OK, merci de vos réponses.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  10. #10
    Membre expérimenté
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 727
    Points
    1 727
    Par défaut
    Et si on fait ça, le compilateur va couiner?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int *end = &tab_1[11]; /*element is non-existent */

  11. #11
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Citation Envoyé par Gruik
    Et si on fait ça, le compilateur va couiner?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int *end = &tab_1[11]; /*element is non-existent */
    Non même avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int *end = &tab_1[1000];
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  12. #12
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut
    Citation Envoyé par Gruik
    Et si on fait ça, le compilateur va couiner?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int *end = &tab_1[11]; /*element is non-existent */
    Non, le compilateur ne dira rien. Mais end ne sert à rien dans ce cas.

  13. #13
    Membre expérimenté
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 727
    Points
    1 727
    Par défaut
    Ok, en relisant je commence à piger ce qu'ils veulent dire, mais je trouve ça debile
    If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow
    Je vois pas pourquoi lire une adresse produirait un overflow
    Est ce que comparer un pointeur avec NULL provoque un segfault? nan. Pareil si on testait "ptr < (int *)0xffffffff".

  14. #14
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par DaZumba
    Non, le compilateur ne dira rien. Mais end ne sert à rien dans ce cas.
    end contient une valeur qui est une adresse valide que l'on peut tester (boucle for, par exemple), mais qu'on ne peut pas déréférencer.
    Pas de Wi-Fi à la maison : CPL

  15. #15
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Gruik
    Ok, en relisant je commence à piger ce qu'ils veulent dire, mais je trouve ça debile

    Je vois pas pourquoi lire une adresse produirait un overflow
    Est ce que comparer un pointeur avec NULL provoque un segfault? nan. Pareil si on testait "ptr < (int *)0xffffffff".
    La valeur pourrait être un overflow. Imagine une machine gérant 16 bits d'adresse (8051, par exemple) :
    L'adresse d'un tableau de 16 char (10h) peut se trouver à FFEF, car FFEF+10 = FFFF qui est une adresse valide.

    Par contre, elle ne peut être en FFF0, car FFF0+10 est invalide (overflow). J'imagine que lors de la compilation, des indication sont données au linker pour qu'il veille à ça.
    Pas de Wi-Fi à la maison : CPL

  16. #16
    Membre expérimenté
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 727
    Points
    1 727
    Par défaut
    Ah bien vu...
    Le compilateur devrait donc pas mettre le tableau à l'adresse FFEF mais à FFEE pour que end ne depasse pas FFFF

  17. #17
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Gruik
    Ah bien vu...
    Le compilateur devrait donc pas mettre le tableau à l'adresse FFEF mais à FFEE pour que end ne depasse pas FFFF
    Je me suis gouraÿ ? c'est possible...
    Pas de Wi-Fi à la maison : CPL

  18. #18
    Membre éprouvé

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

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Points : 1 067
    Points
    1 067
    Par défaut
    Citation Envoyé par Gruik
    Et si on fait ça, le compilateur va couiner?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int *end = &tab_1[11]; /*element is non-existent */
    Non.
    Ne pas oublier que les tableaux en C ne sont qu'une commodité de notation, rien de plus.
    Autrement dit, écrire " tab_1[11] " est équivalent à " *( tab_1 + 11 ) ", soit...faire une addition et aller chercher ce vers quoi le résultat pointe. Et il n'y a pas de raison que le compilateur râle pour une addition...
    Enfin, c'est comme ça que je le comprends...
    Un problème bien exposé
    est, pour moitié, solutionné. / La connaissance s'accroît quand on la partage, pas quand on l'impose. / La violence est le langage des faibles.

  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
    Il y a des compilos qui mettent un warning pour un indice hors tableau statique.
    Mais j'ignore s'ils prennent en compte que pour un tableau de 1à cases, &tab[10] est OK du moemnt qu'on ne le déreférence pas.

    Et si j'ai bien compris l'extrait de la norme, &tab[11] n'est pas spécifié et dépend de l'implémentation...
    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 expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    end contient une valeur qui est une adresse valide que l'on peut tester (boucle for, par exemple), mais qu'on ne peut pas déréférencer.
    Oui, c'est ce que j'ai deja ecrit. Ce que je voulais dire, c'est que pour int s[10]; prendre int *end = &s[10]; peut servir dans une boucle for. Prendre *end = &s[11]; par contre n'a aucun interet pratique, la question est donc inutile.

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

Discussions similaires

  1. [WD11] rangement dans une zone mémoire
    Par Yaone dans le forum WinDev
    Réponses: 5
    Dernier message: 29/03/2007, 11h10
  2. Créer une zone visible qu'après un clic sur une zone
    Par spec10 dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 05/11/2006, 04h00
  3. utilisation d'une zone mémoire dans un formulaire
    Par pursang25 dans le forum Access
    Réponses: 3
    Dernier message: 29/06/2006, 12h41
  4. Réponses: 28
    Dernier message: 01/12/2005, 22h43
  5. Tester qu'un pointeur pointe une zone mémoire valide
    Par Captain_JS dans le forum C++Builder
    Réponses: 2
    Dernier message: 25/08/2005, 19h23

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