Partage
  • Partager sur Facebook
  • Partager sur Twitter

Violation d'accès tableau

    23 décembre 2021 à 15:29:35

    Bonjour,

    je viens de débuter le language C, j'utilise Visual Studio comme IDE, et dans mon programme j'ai créé  une fonction pour copier un chaîne de caractères (un tableau de chars) dans une autre chaîne de caractères, car strcpy() ne marche plus.

    Sauf mon code lève une exception. (Exception levée à 0x00007FF64E901C0F dans Programme.exe : 0xC0000005 : Violation d'accès lors de l'écriture à l'emplacement 0x0000000000000000.)

    Pourtant j'ai juste fait une boucle for qui parcourt le tableau, je ne vois donc pas ce qui cloche.

    Voilà mon code:

    void copierString(char* destination[], const char* source[], int tailleTableau)
    {
    	for (int i = 0; i < tailleTableau; i++)
    	{
    		destination[i] = source[i];
    	}
    }

    Merci d'avance pour votre réponse,

    SniffierPond

    -
    Edité par SniffierPond 23 décembre 2021 à 17:52:29

    • Partager sur Facebook
    • Partager sur Twitter
      23 décembre 2021 à 15:33:05

      Ce qui est étrange c'est d'avoir un tableau de pointeur. En tout cas tu exposes pas tout ton code pour voir ce qui n'est pas bon. Concernant une copie de chaine on peut faire beaucoup plus simple :

      void copierString(char *dst, const char *src)
      {
          while ((*dst++ = *src++))
              ;
      }

      Utilise size_t aussi pour des tailles d'objet, de tableau et indices, c'est fait pour ça.

      -
      Edité par markand 23 décembre 2021 à 15:34:03

      • Partager sur Facebook
      • Partager sur Twitter

      l'azerty est aux dispositions ce que subversion est aux SCM

        23 décembre 2021 à 15:54:00

        Au fait j'essaye juste d'accéder à la ligne d'un tableau avec son adresse passée en paramètre de la fonction.

        Et le compilateur lève une exception pile à la ligne :

        destination[i] = source[i];

        J'ai essayer de changer le code comme ça:

        *destination[i] = *source[i];

        Mais ça ne marchait toujours pas.


        -
        Edité par SniffierPond 23 décembre 2021 à 15:57:33

        • Partager sur Facebook
        • Partager sur Twitter
          23 décembre 2021 à 15:55:59

          SniffierPond a écrit:

          car strcpy() ne marche plus.

          strcpy ne marche plus ? Allons voyons, c'est une blague ?

          Pourquoi tes paramètres destination et source sont des pointeurs de pointeur sur char si tu ne souhaites que copier une chaîne de caractère dans une autre ?



          • Partager sur Facebook
          • Partager sur Twitter
            23 décembre 2021 à 16:40:50

            À mon avis si montrais l'intégralité de ton code ainsi que les warnings tu comprendrais qu'il y a quelque chose qui ne va pas. Ou alors ta fonction est très mal nommée.
            • Partager sur Facebook
            • Partager sur Twitter

            l'azerty est aux dispositions ce que subversion est aux SCM

              23 décembre 2021 à 17:49:04

              On a des tableaux de pointeurs (en tout cas, c'est ce que la fonction montre).
              On risque facilement de se retrouver dans la nature de cette façon.
              char dst[] et const char src[] devraient fonctionner.
              @markand: c'est un peu tordu pour un débutant: assignation, incrémentation et comparaison dans le même énoncé ...
              • Partager sur Facebook
              • Partager sur Twitter

              Le Tout est souvent plus grand que la somme de ses parties.

                23 décembre 2021 à 17:52:01

                Alors quelle est la syntaxe pour avoir un pointeur sur un tableau qui me permet de le manipuler depuis ma fonction?
                • Partager sur Facebook
                • Partager sur Twitter
                  23 décembre 2021 à 18:00:57

                  SniffierPond a écrit:

                  Alors quelle est la syntaxe pour avoir un pointeur sur un tableau qui me permet de le manipuler depuis ma fonction?

                  La syntaxe d'un pointeur sur un tableau (sur son premier élément) est :

                  Type *PointeurSurTableau;

                  Par exemple un pointeur sur un tableau de char (pointeur sur premier char du tableau) :

                  char *pointeurSurTableauDeChar;

                  -
                  Edité par rouIoude 23 décembre 2021 à 23:10:00

                  • Partager sur Facebook
                  • Partager sur Twitter
                    23 décembre 2021 à 19:16:09

                    On risque de se retrouver dans la même discussion que l'autre sujet:
                    https://openclassrooms.com/forum/sujet/adresses-et-tableau-prend-les-mauvaises-valeurs

                    -
                    Edité par PierrotLeFou 23 décembre 2021 à 19:19:01

                    • Partager sur Facebook
                    • Partager sur Twitter

                    Le Tout est souvent plus grand que la somme de ses parties.

                      23 décembre 2021 à 19:27:06

                      SniffierPond a écrit:

                      Alors quelle est la syntaxe pour avoir un pointeur sur un tableau qui me permet de le manipuler depuis ma fonction?

                      Hein ??? Tu n'as pas besoin d'avoir un pointeur sur un tableau pour manipuler le tableau depuis la fonction !

                      Tu as remarqué que 'strcpy' ne marche plus (c'est une boutade !) et tu veux écrire une fonction qui la remplace. Donc son prototype sera :

                      void copierString(char destination[], const char source[], int tailleTableau)

                      (Il existe une autre possibilité, peu importe).

                      Et là ça marchera.

                      (Les autres : vous comprenez pourquoi je trouve que ce n'est pas utile de parler de pointeurs quand on fait des opérations basiques sur les tableaux (cf discussion citée par Pierrot) ? Là j'ai l'impression que SniffierPond a lu que, quand on passe un tableau en paramètres, la fonction utilise un pointeur vers le début du tableau, et ça l'a bien embrouillé.)

                      -
                      Edité par robun 23 décembre 2021 à 19:34:29

                      • Partager sur Facebook
                      • Partager sur Twitter
                        23 décembre 2021 à 20:11:06

                        Hello,

                        Là, on va l'aveuglette.

                        Comme tu débutes, je suppose que le programme ne doit pas être trop conséquent. Je te conseille de poster l'intégralité du code pour que nous puissions t'aider.

                        -
                        Edité par edgarjacobs 23 décembre 2021 à 20:12:26

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Il y a ceux qui font des sauvegardes, et ceux qui n'ont pas encore eu d'incident....

                          23 décembre 2021 à 20:13:35

                          robun a écrit:

                          (Les autres : vous comprenez pourquoi je trouve que ce n'est pas utile de parler de pointeurs quand on fait des opérations basiques sur les tableaux.

                          Oui, je comprend, mais :

                          robun a écrit:

                          Tu n'as pas besoin d'avoir un pointeur sur un tableau pour manipuler le tableau depuis la fonction !

                          ton affirmation est fausse !



                          • Partager sur Facebook
                          • Partager sur Twitter
                            23 décembre 2021 à 21:54:03

                            Pourtant, voici un programme où des fonctions manipulent des tableaux :

                            #include <stdio.h>
                            #define N 200
                            void init_tab(int tab[N], int nb_elem)
                            { /* Initialise un tableau avec les carrés */
                                for (int i = 1; i <= nb_elem; i++)
                                    tab[i-1] = i*i;
                            
                            }
                            void fois_deux(int tab1[N], int tab2[N], int nb_elem)
                            { /* Double les valeurs des éléments */
                                for (int i = 0; i < nb_elem; i++)
                                    tab2[i] = 2.0 * tab1[i];
                            }
                            void affiche(int tab[N], int nb_elem)
                            { /* Affiche les éléments du tableau en ligne */
                                printf("[ ");
                                for (int i = 0; i < nb_elem; i++)
                                    printf("%d ", tab[i]);
                                printf("]\n");    
                            }
                            int main(void)
                            {
                                int tableau[N];
                                int tableaudouble[N];
                                init_tab(tableau, 5);
                                affiche(tableau, 5);
                                fois_deux(tableau, tableaudouble, 5);
                                affiche(tableaudouble, 5);
                                return 0;
                            }

                            De mon point de vue, il n'y a que des tableaux, aucun pointeur, je n'ai même pas besoin d'avoir suivi un cours sur les pointeurs pour faire ça.

                            Après, je sais bien que dans les fonctions, ce sont des pointeurs vers le début des tableaux (donc pas des pointeurs sur tableaux mais bien des pointeurs sur 'int'). Mais ça, c'est la petite cuisine interne du C. Alors oui, le C est un langage qui nécessite souvent de mettre les mains dans le cambouis et d'utiliser cette petite cuisine interne. Ce n'est pas obligatoire dans ce contexte, ni (je trouve) celui de SniffierPond qui souhaite ré-écrire 'strcpy'.

                            -
                            Edité par robun 23 décembre 2021 à 21:57:06

                            • Partager sur Facebook
                            • Partager sur Twitter
                              23 décembre 2021 à 22:21:12

                              robun a écrit:

                              De mon point de vue, il n'y a que des tableaux, aucun pointeur, 

                              C'est ton point de vue, mais c'est faux !

                              • Partager sur Facebook
                              • Partager sur Twitter
                                23 décembre 2021 à 22:34:35

                                Ah, je m'explique mal. De mon point de vue signifiait : vu depuis ma position. Ce n'est pas une question d'opinion mais de position. Je n'ai déclaré aucun pointeur, je n'ai pas utilisé de * ni de &.

                                Du point de vue du compilateur (depuis sa position), il y a bien sûr plein de pointeurs. Mais je n'ai pas à m'en soucier.

                                -
                                Edité par robun 23 décembre 2021 à 22:35:19

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  23 décembre 2021 à 22:47:16

                                  robun a écrit:

                                  Je n'ai déclaré aucun pointeur

                                  Ça aussi c'est faux !

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    24 décembre 2021 à 1:11:07

                                    Bonjour,

                                    tu as plusieurs problèmes, mais le principal est un problème de compréhension autant de comment on représente une chaîne de caractères que «qui fait quoi à quel moment».

                                    Tout d'abord tu dis :

                                    SniffierPond a écrit:

                                    Bonjour,

                                    je viens de débuter le language C, j'utilise Visual Studio comme IDE, et dans mon programme j'ai créé  une fonction pour copier un chaîne de caractères (un tableau de chars) dans une autre chaîne de caractères, car strcpy() ne marche plus.


                                    ok … «strcpy ne marche plus» … tu devrais plutôt dire «j'ai un problème d'utilisation de strcpy» car si strcpy ne fonctionnait plus alors la majorité des programmes de base ne fonctionneraient plus non plus.

                                    Tu dis également «j'ai créé  une fonction pour copier un chaîne de caractères (un tableau de chars) dans une autre chaîne de caractères». Tu parles de «tableau de char» ce qui se traduit par «char  destination[]» or dans ce que tu nous montre on trouve «char *destination[]» qui définit destination comme étant un tableau sur des éléments qui ont pour type char * = pointeur sur char …

                                    Tu dis également :

                                    SniffierPond a écrit:

                                    [...]

                                    Sauf mon code lève une exception. (Exception levée à 0x00007FF64E901C0F dans Programme.exe : 0xC0000005 : Violation d'accès lors de l'écriture à l'emplacement 0x0000000000000000.)

                                    avec :

                                    SniffierPond a écrit:

                                    [...]
                                    Et le compilateur lève une exception pile à la ligne :

                                    destination[i] = source[i];

                                    Ce n'est pas le compilo qui lève une exception … mais l'OS qui intercepte une exception levée par le programme compilé lorsqu'il est exécuté.

                                    Le compilo t'aura sans doute émit quelques warnings … tout au plus.

                                    Si tu veux créer une fonction copierString qui prend un tableau de char source de longueur tailleTableau et en copie le contenu dans un tableau de char destination (de taille suffisante) alors il te faudra écrire :

                                    void copierString(char destination[], const char source[], int tailleTableau) {
                                    for(int i=0; i<tailleTableau; i++)
                                    destination[i]=source[i];
                                    }
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      24 décembre 2021 à 1:41:38

                                      Et on va partir la discussion sur ce qu'est un "tableau de char" et une "chaîne de char" dont la seule différence est la présence d'un caractère de fin de chaîne représenté par '\0' qui vaut 0 de toute façon.
                                      Et pourquoi strcpy ne marche plus? N'est-ce pas parce qu'on n'a pas de caractère de fin de chaîne?

                                      Le langage C amène lui-même une confusion.
                                      Je peux avoir  char dst[] ou char *dst dans le prototype
                                      et utiliser *dst ou dst[i] dans la fonction, c'est interchangeable.
                                      (voir le code de markand)
                                      Comment voulez-vous qu'un débutant s'y retrouve?

                                      -
                                      Edité par PierrotLeFou 24 décembre 2021 à 1:50:11

                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      Le Tout est souvent plus grand que la somme de ses parties.

                                        24 décembre 2021 à 1:50:02

                                        Pierrot, quelqu'un qui écrit en Français «tableau de char» mais en C «char * truc[]» a forcément un gros problème de compréhension concernant les types (peu importe que le représentation usuelle des chaînes se fasse en ASCIIZ dans la libc via la famille de fonctions str*).
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          24 décembre 2021 à 1:57:59

                                          Alors où ttrouver la meilleure doc pour renseigner le PO?
                                          Nos explications ne semblent pas l'avoir convaincu.
                                          • Partager sur Facebook
                                          • Partager sur Twitter

                                          Le Tout est souvent plus grand que la somme de ses parties.

                                            24 décembre 2021 à 2:03:44

                                            C'est simple : https://zestedesavoir.com/tutoriels/755/le-langage-c-1/1042_les-bases-du-langage-c/ plutôt que le cours ici … mais apprendre l'écosystème C est difficile.
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              24 décembre 2021 à 9:48:54

                                              White Crow a écrit:

                                              Pierrot, quelqu'un qui écrit en Français «tableau de char» mais en C «char * truc[]» a forcément un gros problème de compréhension concernant les types (peu importe que le représentation usuelle des chaînes se fasse en ASCIIZ dans la libc via la famille de fonctions str*).


                                              J'y vois une confusion avec les deux façons (équivalentes) de déclarer la fonction :

                                              fonction(char tableau[])

                                              et

                                              fonction(char *tableau)

                                              ----------------------------

                                              rouIoude a écrit:

                                              robun a écrit:

                                              Je n'ai déclaré aucun pointeur

                                              Ça aussi c'est faux !

                                              D'un point de vue sémantique (donc du point de vue humain) c'est vrai. Du point de vue du compilateur, je m'en fiche, c'est son problème. (Je m'en fiche dans ce contexte, où je n'ai pas besoin de savoir que c'est en réalité un pointeur qui est utilisé dans la fonction.)

                                              -
                                              Edité par robun 24 décembre 2021 à 9:49:51

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                24 décembre 2021 à 10:32:54

                                                Tu t'en fiche, ok, mais traiter le pointeur comme un pointeur est parfois très pratique, Si je prend la fonction strcpy comme l'as écris markand j'écris comment ? Comme ça :

                                                void copierString(char dst[], const char src[])
                                                {
                                                    while ((dst++[0] = src++[0]));
                                                }

                                                ça marche, ok !

                                                Après si on veux faire abstraction des pointeurs, on ne fait pas du C !

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  24 décembre 2021 à 13:11:44

                                                  Ah oui, les pointeurs sont très pratiques ! L'exemple de markand est en effet éloquent. Et je suis sûr qu'un professionnel doit faire ainsi. Mais ce n'est pas la méthode qu'avait utilisée au début SniffierPond, qui a dit être débutant. Je trouve que pour corriger son programme, les pointeurs n'étaient donc pas nécessaires.

                                                  Quant à s'interdire d'utiliser le C si on ne veut pas utiliser de pointeurs, je fais ce que je veux ! :) En fait, pour mes projets personnels, j'utilise le C principalement parce que c'est le langage avec lequel je suis le plus à l'aise pour faire de la programmation structurée. Il me semble que le C n'est pas qu'un assembleur de haut niveau, il a d'autres qualités.

                                                  -
                                                  Edité par robun 24 décembre 2021 à 13:12:09

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    24 décembre 2021 à 13:43:54

                                                    robun a écrit:

                                                    Je trouve que pour corriger son programme, les pointeurs n'étaient donc pas nécessaires.

                                                    Faudrait déjà savoir ce qu'il lui envoi à sa fonction ? Parce que pour que ça ne marche pas avec strcpy ?!?

                                                    robun a écrit:

                                                    Là j'ai l'impression que SniffierPond a lu que, quand on passe un tableau en paramètres, la fonction utilise un pointeur vers le début du tableau, et ça l'a bien embrouillé.)

                                                    C'est pourtant la vérité ! Et :

                                                    SniffierPond a écrit:

                                                    Au fait j'essaye juste d'accéder à la ligne d'un tableau avec son adresse passée en paramètre de la fonction.

                                                    Il a bien conscience de passer l'adresse du tableau (adresse de son premier élément).

                                                    Sinon comment la fonction pourrait modifier le tableau passé en paramètre ? Ça ne serait plus cohérent avec les autres type de variable. 

                                                    robun a écrit:

                                                    je fais ce que je veux !

                                                    Tout a fait !







                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      24 décembre 2021 à 14:12:55

                                                      C'est vrai qu'on ne sait toujours pas pourquoi 'strcpy' ne marche plus. A-t-il été réparé ? Dans le doute, je préfère ne plus l'utiliser ! ;)

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        24 décembre 2021 à 15:11:32

                                                        Tu n'as qu'à prendre le code de markand et appeler la fonction "strcpy" :)
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter

                                                        Le Tout est souvent plus grand que la somme de ses parties.

                                                          25 décembre 2021 à 21:07:41

                                                          Notez toutefois que même si un tableau peut être converti en pointeur ça reste des déclarations différentes. Une fonction qui prend un tableau a besoin de connaitre la définition de l'objet et ça c'est pas pratique.

                                                          struct unknown;
                                                          
                                                          void f(struct unknown tab[]) {} // FAIL.
                                                          void g(struct unknown *ptr) {}  // OK.
                                                          



                                                          • Partager sur Facebook
                                                          • Partager sur Twitter

                                                          l'azerty est aux dispositions ce que subversion est aux SCM

                                                            26 décembre 2021 à 13:56:26

                                                            Alors c'est intéressant comme comportement car cela ne devrait pas arriver en fait. On peut le constater avec gcc et clang mais pas icc (le compilo Intel) ni msvc … (testé sur godbolt).

                                                             Le pourquoi cela ne devrait pas se produire est simple. La norme à la section 6.7.6.3 Function declarators spécifie :

                                                            • à l'alinéa 12 : « If the function declarator is not part of a definition of that function, parameters may have incomplete type [...] » ;
                                                            • à l'alinéa 4 : « After adjustment, the parameters in a parameter type list in a function declarator that is part of a definition of that function shall not have incomplete type.»
                                                              où l'alinéa 7 précise : «A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’ [...]»

                                                            Ces interprétations différentes pourraient provenir d'une interprétation de la section 6.2.1 Scope of Identifiers où l'alinéa 4 spécifie la visibilité des paramètres lors d'une définition ou d'une déclaration sans préciser l'ajustement éventuel des paramètres de type (tableau de …).

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              27 décembre 2021 à 3:59:23

                                                              markand a écrit:

                                                              Notez toutefois que même si un tableau peut être converti en pointeur ça reste des déclarations différentes. Une fonction qui prend un tableau a besoin de connaitre la définition de l'objet et ça c'est pas pratique.

                                                              struct unknown;
                                                              
                                                              void f(struct unknown tab[]) {} // FAIL.
                                                              void g(struct unknown *ptr) {}  // OK.
                                                              



                                                              Oh, merci, une subtilité que je n'avais jamais remarquée!

                                                              -
                                                              Edité par Marc Mongenet 27 décembre 2021 à 4:00:43

                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Violation d'accès tableau

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              • Editeur
                                                              • Markdown