Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème très très étrange

avec la fonction realloc

Sujet résolu
    28 juillet 2007 à 16:51:05

    Bonjour,

    Je viens de rencontrer un problème très très étrange (c'était dit dans le titre :) )

    Le voici :

    Je faisais des essais sur la manière d'utiliser de realloc, lorsque je me suis aperçu que le code que j'avais fais ne fonctionne que si je rajoute une certaine partie de code qui n'a rien a voir avec le reste. (expliqué comme ça, c'est pas très clair... ;) , mais ça devrait le devenir avec le code et quelques explications supplementaires)


    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <winsock2.h>



    int main (int argc, char *argv[])
    {

        //--------------------------------------------------------------------------
        //       PARTIE INCOMPREHENSIBLEMENT NECESSAIRE AU FONCTIONNEMENT
        //                   DE LA RE-ALLOCATION DU TABLEAU
        //
        //          CETTE PARTIE N'A NORMALEMENT AUCUNE RAISON D'ETRE
        //                         DANS MON PROGRAMME
        //--------------------------------------------------------------------------

        WSADATA WSAData;
        int err = WSAStartup (MAKEWORD (2, 0), &WSAData);


            HOSTENT *hp = gethostbyname ("siteduzero.com");


        WSACleanup ();








        //--------------------------------------------------------------------------
        //                      DECLARATION DES VARIABLES
        //--------------------------------------------------------------------------

        char **tableau = NULL;
        char hauteur1 = 3;
        char longueur1 = 10;
        char hauteur2 = 5;
        char longueur2 = 20;
        char i = 0;


        //--------------------------------------------------------------------------
        //                   ALLOCATION DE MEMOIRE AU TABLEAU
        //--------------------------------------------------------------------------

        tableau = malloc(hauteur1*(sizeof(*tableau)));
        for(i=0; i<hauteur1; i++)
        {
            tableau[i] = malloc(longueur1*(sizeof(**tableau)));
           sprintf(tableau[i], "SdZ");
        }


        //--------------------------------------------------------------------------
        //                    AFFICHAGE DU CONTENU DU TABLEAU
        //--------------------------------------------------------------------------

        for(i=0; i<hauteur1; i++)
        {
            printf("%s\n", tableau[i]);
        }


        //--------------------------------------------------------------------------
        //                  RE-ALLOCATION DE MEMOIRE AU TABLEAU
        //--------------------------------------------------------------------------

        tableau = realloc(tableau, hauteur2*(sizeof(*tableau)));
        for(i=0; i<hauteur2; i++)
        {
            tableau[i] = realloc(tableau[i], longueur2*(sizeof(**tableau)));
            strcpy(tableau[i], "Le Site du Zer0");
        }


        //--------------------------------------------------------------------------
        //                    AFFICHAGE DU CONTENU DU TABLEAU
        //--------------------------------------------------------------------------

        for(i=0; i<hauteur2; i++)
        {
            printf("%s\n", tableau[i]);
        }

        free(tableau);


      return 0;

    }
     


    Ce code tel que je viens de le poster fonctionne parfaitement (même si on peut me reprocher qu'il ne tient pas compte des allocations impossibles...)

    mais,

    <code type ="c">
    WSADATA WSAData;
    int err = WSAStartup (MAKEWORD (2, 0), &WSAData);


    HOSTENT *hp = gethostbyname ("siteduzero.com");


    WSACleanup ();
    </code>

    Cette partie du code n'a rien a faire dans mon programme.
    Néanmoins, si je l'enlève, le programme plante lors de son execution, au niveau de la re-allocation de mémoire.

    Je vois pas du tout le rapport entre la fonction realloc et la fonction gethostbyname, c'est pourquoi je vous pose la question.

    Comment puis-je faire pour que mon code fonctionne sans contenir la fonction gethostbyname ?
    • Partager sur Facebook
    • Partager sur Twitter
      28 juillet 2007 à 17:01:46

      char hauteur1 = 3;
          char longueur1 = 10;
          char hauteur2 = 5;
          char longueur2 = 20;
          char i = 0;



      Pourquoi t'utilise un char pour stocker des nombres , c'est illogique ?

      #include <stdio.h>

       [...]

      #define  HAUTEUR1  3
      #define LONGUEUR1  10
      #define HAUTEUR2  5
      #define LONGUEUR2  20

      [...]


      int i;


      • Partager sur Facebook
      • Partager sur Twitter
        28 juillet 2007 à 17:14:56

        j'ai remplacé les "char" par des "long" (sauf bien sur le "char" du tableau), mais le probleme est toujours là... :(
        • Partager sur Facebook
        • Partager sur Twitter
          28 juillet 2007 à 23:40:48

          Essaye en enlevant la partie inutile et la lib winsock2.
          //#include <winsock2.h>
           
          • Partager sur Facebook
          • Partager sur Twitter
            28 juillet 2007 à 23:57:50

            je viens d'essayer, et ça ne marche toujours pas...

            Je comprends pas ce problème... la fonction realloc n'a pourtant rien a voir avec la fonction gethostbyname...(enfin, a mon niveau de connaissances tout du moins...)
            • Partager sur Facebook
            • Partager sur Twitter
              29 juillet 2007 à 0:18:29

              Citation : scriptoff


              Pourquoi t'utilise un char pour stocker des nombres , c'est illogique ?


              Non, le type char fait partie des types entiers. S'il faut travailler avec des gros tableaux de petits entiers, je crois que ça se fait assez couramment (je l'ai vu sur des calculatrices TI par exemple).
              • Partager sur Facebook
              • Partager sur Twitter
                29 juillet 2007 à 0:20:33

                Sinon, laissse moi essayer d'être clair (essayer, je dis bien :p ...) en t'expliquant pourquoi ton algo ne fonctionne pas. Retroussez vous manches, nous voilà partis :
                Tout d'abord, tu crée une variable tableau qui est un pointeur vers un tableau de pointeurs vers des tableaux (je vous l'avais bien dit que ce serait chiant difficile), soit pour simplifier un pointeur vers un tableau en deux dimensions.
                quand tu fait "realloc(tableau, hauteur2 * sizeof(*tableau));", le processeur fait en fait un "free(tableau)" et un "tableau = malloc(hauteur2 * sizeof(*tableau));". Ton tableau a donc été réinitialisé et tous les éléments de tableau (des pointeurs, eux aussi) ont été perdus (comme quand tu realloc() un tableau de long, les éléments ne sont pas les mêmes après la réallocation). Ensuite (et c'est là qu'il y a problème), tu parcours ton tableau réinitialisé et tu fait des realloc de tous ses éléments (que tu ne connais toujours pas et le processeur non plus), ce qui équivaut, comme je l'ai dit plus haut, à faire un "free(tableau[i]);" et ... "quoi" dit le processeur "on libère de la mémoire que l'on a pas allouée, c'est mal ! quelqu'un sera puni..." et devine qui est ce quelqu'un...
                ...oui, tu as deviné, c'est "l'immonde programmeur qui a osé pondre une telle saleté" (en proceseur dans le texte :p ), c'est à dire toi.
                En fait, si tu veux le faire proprement, il faut :
                1. libérer la mémoire des sous tableaux
                2. réallouer la mémoire du grand tableau
                3. allouer la mémoire des petits tableaux (et pas la réallouer)

                Cela donne

                for(i = 0; i < hauteur1; i++)
                {
                   free(tableau[i]);
                }

                realloc(tableau, hauteur2 * sizeof(*tableau));

                for(i = 0; i < hauteur2; i++)
                {
                   tableau[i] = malloc(longueur2 * sizeof(**tableau));
                }


                et si tu codes en C++, tu peux surcharger la fonction realloc avec comme prototype :

                void*  realloc(void** tableau, long* newSizes);


                Je te laisse trouver le reste...

                Bonne nuit,

                EDIT : j'ai vu une autre faute (presque la même, ne t'inquiète pas :p ) quand tu fais "free(tableau);" à la fin, il faut libérer les sous-tableaux d'abord. En fait, il y a une règle : quand tu fait un malloc (ou un realloc) sur un pointeur, il faut IMPERATIVEMENT faire un "free(pointeur);" à la suite selon la procédure LIFO (argot de programmeur ;) qui veut dire 'Last In First Out', dernier à entrer, premier à sortir) donc 'dernier alloué, premier libéré'.

                Dans ton code, tu as

                    tableau = malloc(hauteur1 * (sizeof(*tableau)));

                    for(i = 0; i < hauteur1; i++)
                    {
                        tableau[i] = malloc(longueur1 * (sizeof(**tableau)));
                    }


                tu dois donc, à la fin, obligatoirement avoir

                    for(i = 0; i < hauteur2; i++)
                    {
                        free(tableau[i]);
                    }

                    free(tableau);
                • Partager sur Facebook
                • Partager sur Twitter
                  29 juillet 2007 à 11:07:04

                  :) Merci beaucoup raton-laveur boiteux, j'ai du relire plusieurs fois ta réponse avant de tout comprendre (ceci dit elle est bien expliquée), et je pense avoir compris maintenant.

                  A partir d'aujourd'hui je serais gentil avec mon ordinateur, et j'essaierais de ne plus me comporter en "immonde programmeur qui a osé pondre une telle saleté" :(

                  je vais essayer de faire ce que tu m'as dis, puis je m'en retournerais sur le chemin caillouteux de l'apprentissage (très très caillouteux parfois ^^ )
                  • Partager sur Facebook
                  • Partager sur Twitter
                    29 juillet 2007 à 14:46:44

                    Excuse-moi de la formule, j'étais fatigué hier soir (ceci dit, elle est percutante, n'est-ce pas :p ? ). Et c'est bien à toi d'avoir compris tes erreurs et de vouloir t'améliorer (c'est comme ça qu'on y arrive ^^ ).

                    Bonne continuation :)
                    • Partager sur Facebook
                    • Partager sur Twitter

                    Problème très très étrange

                    × 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