Partage
  • Partager sur Facebook
  • Partager sur Twitter

Réallouer de la mémoire à un tableau depuis un ptr

Sujet résolu
    17 août 2019 à 20:36:02

    (Désolé pour la fin du titre qui n'est pas complète, je voulais bien sûr parler de "pointeur").

    Bonsoir :)

    Pour les besoins d'un programme nécessitant les performances que le C a à offrir, je dois jouer avec les pointeurs.

    Dans ce cas précis, j'ai une structure contenant des informations, souhaitant posséder plusieurs informations, il me faut donc un tableau de cette structure, et pour la modifier depuis des fonctions, il me faut un pointeur sur ce tableau de structure.

    Voici un exemple qui résume la situation :

    typedef struct Data {
        int x;
        char* y;
        ...
    } Data;
    
    void initDico(Data** array, size_t initSize) {
        *array = (Data*)malloc(initSize * sizeof(Data));
    }
    
    void addItem(Data** array, Data item){
        // Je dois donc réallouer la mémoire
        *array = realloc(*dico, 20); // '20' c'est un exemple évidemment, afin de ne pas churcharger
        // Ajout d'un élément
    }
    
    Data* arrayOfData;
    
    init(&arrayOfData, 1); // J'initialise la taille du tableau à 1
    addItem(&arrayOfData, /* un nouvel élément du type "Data" */);
    

    Lorsque je teste, le programme s'arrête durant l'exécution, donc quelque chose c'est mal produit, et le problème survient à la 13ème ligne dans ce code, lorsque la fonction d'ajout d'élément est appelée.

    Il y a peut-être d'autres choses à modifier dans ce code au niveau des allocations dynamiques, mais je ne vois pas en quoi ce que j'ai fais fait crasher le programme...

    Si quelqu'un pouvait m'aider à résoudre ça ^^'

    • Partager sur Facebook
    • Partager sur Twitter
    Le doute est le commencement de la sagesse
      17 août 2019 à 21:08:19

      Si tu veux agrandir ton tableau, c'est le pointeur sur ton tableau qu'il faut envoyer à realloc pas le pointeur dico qui ne sort de je ne sais où !

      • Partager sur Facebook
      • Partager sur Twitter
        17 août 2019 à 21:15:58

        Pardon, `dico` est le nom réel dans mon code, j'ai fait une erreur de frappe. Il faut juste remplacer `dico` par `array` :

        typedef struct Data {
            int x;
            char* y;
            ...
        } Data;
         
        void init(Data** array, size_t initSize) {
            *array = (Data*)malloc(initSize * sizeof(Data));
        }
         
        void addItem(Data** array, Data item){
            // Je dois donc réallouer la mémoire
            *array = realloc(*array, 20); // '20' c'est un exemple évidemment, afin de ne pas churcharger
            // Ajout d'un élément
        }
         
        Data* arrayOfData;
         
        init(&arrayOfData, 1); // J'initialise la taille du tableau à 1
        addItem(&arrayOfData, /* un nouvel élément du type "Data" */);

        Mais ça ne résout pas le problème… :/

        -
        Edité par Geralt de Riv 17 août 2019 à 21:19:18

        • Partager sur Facebook
        • Partager sur Twitter
        Le doute est le commencement de la sagesse
          17 août 2019 à 21:38:50

          Il est fort peu probable que ce soit la ligne 13 qui fasse planter ton programme, l'erreur doit être ailleurs ! Dans une partie du code que tu nous ne montre pas !
          • Partager sur Facebook
          • Partager sur Twitter
            17 août 2019 à 22:07:49

            Salut,

            Le bout de code que tu fournis ne fail pas chez moi. Peux-tu donner le message d'erreur que tu obtiens, ainsi que le scénario dans lequel tu l'obtiens?

            • Partager sur Facebook
            • Partager sur Twitter
              17 août 2019 à 22:26:58

              Désolé :euh:; bon voici mon code réel et semi-entier :

              typedef struct Variable Variable; // Défini autre part, mais le contenu n'est pas intéressant ici
              typedef struct {
                  Variable* array;
                  size_t
                      size, // Taille allouée
                      used; // Espace utilisé
              } VarDico;
              
              void initDico(VarDico* dico, size_t initSize) {
                  dico->array = (Variable*)malloc(initSize * sizeof(Variable));
                  dico->used = 0;
                  dico->size = initSize;
              }
              
              void addVariable(VarDico* dico, Variable new) {
                  if (dico->used == dico->size) {
                      dico->size *= 2; // Je double la taille allouée à chaque fois
                      dico->array = (Variable*)realloc(dico->array, dico->size * sizeof(Variable));   
                      if (dico->array == NULL) perror("Out of memory");
                  }
                  dico->array[dico->used++] = new; // J'ajoute le nouvel élément dans le tableau
              }
              
              // Usage :
              
              VarDico dico;
              initDico(&dico, 1);
              Variable new = /* Nouvelle variable */;
              printf("\nAdding variable…\n"); addVariable(&dico, new); printf("\nEnd of program\n");

              Plus que ça serait futile, il me semble; désolé de ne pas l'avoir montré plus tôt mais je pense faire parti des programmeurs qui ont un peu peur de montrer leur code…

              Donc là, il affiche "Adding variable..." mais crache dans la fonction addVariable.

              Au début, j'initialise la taille à 1 élément, dico.used est donc différent de dico.size, une allocation de mémoire n'étant donc pas nécessaire, le programme passe donc à l'instruction suivante :

              dico->array[dico->used++] = new;

              Incrémentant donc la variable used, ce qui permettra de faire une nouvelle allocation de mémoire la prochaine fois et ainsi de suite.

              Donc effectivement, ça ne provient probablement pas de "la ligne 13" après réflexion, ça ne pourrait venir que de l'instruction d'ajout de l'élément.

              @Melin Alexandre

              Donc voilà le code :D

              Par contre je n'obtiens aucune erreur de compilation, ce n'est que le programme qui s'arrête en cours de route.

              -
              Edité par Geralt de Riv 17 août 2019 à 22:28:20

              • Partager sur Facebook
              • Partager sur Twitter
              Le doute est le commencement de la sagesse
                17 août 2019 à 22:42:29

                Ce n'est toujours pas dans la partie que tu nous montres !
                • Partager sur Facebook
                • Partager sur Twitter
                  17 août 2019 à 22:49:24

                  Merci pour le code, il est toujours important de montrer le code pour qu'on puisse t'aider ;)
                  Mais là encore, ton code fonctionne très bien chez moi avec une structure variable qui ne possède qu'un int en tant qu'attribut. Est ce que l'ajout de la première variable dans ton tableau fonctionne?

                  • Partager sur Facebook
                  • Partager sur Twitter
                    17 août 2019 à 22:55:04

                    Écoutez, je suis vraiment désolé de vous avoir fait perde votre temps… >_<

                    J'ai finalement trouvé "où" était l'erreur, mon code était en effet fonctionnel, mais pour une raison obscure, après avoir effacé les fichiers objets générés par GCC (ce que je ne fais pratiquement jamais parce que je n'y pense pas), le programma a correctement fonctionné (pourtant c'était le même qu'avant).

                    Si vous avez une explication à ça… :o

                    Je vous remercie pour votre patience tout de même. 

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Le doute est le commencement de la sagesse
                      17 août 2019 à 22:58:15

                      C'est nice que ton problème soit résolu. Si effacer les fichiers a tout remis en ordre c'est que tu devais avoir une ancienne version d'un fichier dans ta chaine de compilation(par conséquent un fichier qui contenait du code erroné ou ancien)^^
                      Tu procèdes comment pour compiler ton projet (makefile, tout à la main...) ?
                      • Partager sur Facebook
                      • Partager sur Twitter
                        17 août 2019 à 23:02:57

                        Melin Alexandre a écrit:

                        Si effacer les fichiers a tout remis en ordre c'est que tu devais avoir une ancienne version d'un fichier dans ta chaine de compilation(par conséquent un fichier qui contenait du code erroné ou ancien)

                        Oui, ça doit surement être ça ^^

                        Melin Alexandre a écrit:

                        Tu procèdes comment pour compiler ton projet (makefile, tout à la main...) ?

                        J'utilise un Makefile, oui.
                        • Partager sur Facebook
                        • Partager sur Twitter
                        Le doute est le commencement de la sagesse
                          17 août 2019 à 23:04:15

                          Geralt de Riv a écrit:

                          J'utilise un Makefile, oui.

                          Revois le et vérifie que tout est dans le bon ordre par rapport à la chaine de compilation ;)

                          • Partager sur Facebook
                          • Partager sur Twitter
                            17 août 2019 à 23:14:20

                            D'accord, je vais faire ça :)

                            • Partager sur Facebook
                            • Partager sur Twitter
                            Le doute est le commencement de la sagesse
                              30 août 2019 à 20:07:12

                              Le Makefile est beaucoup moins galère quand on tire profit

                              • des règles et dépendances implicites du Makefile
                              • de la génération des dépendances explicites par le compilateur

                              Soit par exemple un programme avec un main dans prog.c et des sources foo.c, bar.c, baz.c ainsi que les .h, les uns dépendant des autres, etc.

                              Voila le Makefile

                              #
                              # Les options de compilation
                              #
                              CFLAGS = -std=c18 
                              CFLAGS += -Wall -Wextra
                              CFLAGS += -MD               # génération des dépendances
                              
                              #
                              # mon projet
                              #
                              
                              prog : prog.o foo.o bar.o baz.o      # that's all !
                              
                              -include $(wildcard *.d)    # inclusion des dépendances
                              
                              

                              Explication :

                              • quand on compile un programme toto.c avec l'option -MD de gcc (et llvm ?), ça génère en même temps un fichier toto.d contenant un petit makefile avec ses dépendances (les fichiers .h qu'il inclut, directement ou pas)
                              • l'include du Makefile dit d'inclure ces makefiles, avant d'exécuter les cible voulues
                              • la fabrication de prog.o se fait implicitement, puisqu'il traine un prog.c dans le répertoire, en utilisant la macro COMPILE.c, qui fait ce qu'il faut en utilisant les variables CFLAGS etc.
                              • la fabrication de prog à partir de prog.o et d'autres se fait implicitement en lançant une macro LINK.c
                              • les dépendances se mettent donc à jour toutes seules, automagiquement.

                              Piège à con (moi) : ne pas mettre l'include au début (parce que make lancera la première cible contenue dans le premier .d).

                              -
                              Edité par michelbillaud 30 août 2019 à 20:10:17

                              • Partager sur Facebook
                              • Partager sur Twitter

                              Réallouer de la mémoire à un tableau depuis un ptr

                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                              • Editeur
                              • Markdown