Partage
  • Partager sur Facebook
  • Partager sur Twitter

Erreur de segmentation (realloc - malloc)

Problème de manipulations de tableaux dynamique et de fichiers

Sujet résolu
    9 août 2017 à 21:20:39

    Bonjour,

    Je viens à vous aujourd'hui pour vous exposer mon problème sur lequel je sèche depuis plusieurs jours maintenant.

    En effet, j'essaie de récupérer un nombre de caractère dans un fichier. Sachant que je ne connais pas ce nombre exacte (car il peut changer) j'utilise l'allocation dynamique de mémoire à l'aide de malloc et de realloc.

    Le problème est que l'orsque j'arrive au 3 ème caractère, le programme stop et j'ai le droit à un erreur de segmentation. (Segmentation fault (Core dumped)).
    J'imagine que c'est mon utilisation de realloc qui doit m'échapper et donc que je fais un dépassement de mémoire. Mais malgrés tous mes tests et recherche, je n'arrive pas à trouver ou.

    Je vous met mon code (seulement la boucle charger de récupérer les caractères du fichier).

    // Get all objects in map file
    while (car != EOF)
    {
        if ((car != '\n') && (car != '\r'))
        {
            nbObjects++;
    
            if (nbObjects == 1)
            {
                *objects = (char*) malloc(nbObjects);
            }
            else
            {
                *objects = (char*) realloc(*objects, nbObjects);
            }
    
            if (*objects == NULL)
            {
                error("The memory allocation has failed", false);
            }
    
            *objects[nbObjects - 1] = car;
        }
    }

    Les variables sont bien évidemment déclarer plus haut.

    Je vous remercie de l'attention que vous porterez à mon problème.

    PS: A savoir que j'utilise l'étoile devant le pointeur objects car je l'ai récupérer dans les paramètres d'une fonction. Et donc, j'ai utiliser le double pointeur.


    Bonne soirée ! :D

    -
    Edité par peridot69 9 août 2017 à 21:27:59

    • Partager sur Facebook
    • Partager sur Twitter
    printf("Les rudiments de la programmation ? Nan mais Hello quoi !");
    Anonyme
      9 août 2017 à 22:07:48

      Salut,

      Nous sommes donc d'accord qu'objet est un pointeur sur pointeur ? Déjà que les pointeurs sont des nids à erreurs alors les pointeurs sur pointeurs.... Je veux dire que si tu peux éviter de les utiliser, il faut le faire. Après il y a certainement des cas où on a pas le choix, mais autant que possible il faut éviter.

      Par exemple faire comme la fonction realloc, tu prends en paramètre un simple pointeur et tu renvois sa nouvelle adresse.
      Voici la méthode que j'utilise, certainement pas la meilleure mais elle me suffit.

      //Fonction qui augmente la taille d'un bloc mémoire de 6, complètement inutile mais c'est pour l'exemple
      char* monAlloc(char* ptr, size_t size, int* erreur)
      {
      	ptr=(char*) realloc(ptr, size+6);
      	
      	if(ptr)
      	{
      		*erreur=0;
      		return ptr;
      	}
      	else
      	{
      		*erreur = TON_CODE_ERREUR;
      		return NULL;
      	}
      }

      Via cette fonction tu peux renvoyer toute une variété de codes d'erreur grâce au pointeur "int* erreur" (même si ici c'est complètement inutile, mais tu vois ainsi comment faire si ça te prive du retour d'un int par exemple), et en même temps je n'ai pas de pointeurs sur pointeurs.

      -
      Edité par Anonyme 9 août 2017 à 22:08:56

      • Partager sur Facebook
      • Partager sur Twitter
        9 août 2017 à 22:16:24

        En effet, j'avais étudier cette solution, le problème est que le pointeur en lui même j'ai besoin de le créer et possiblement d'utiliser avant l'utilisation de la fonction qui cherche les caractère.

        De plus, j'aurais besoin à tous moment de la taille du tableau (le nbObjects renvoyer). Ce qui fait que je ne peux pas me passer de cette information et je doit donc la renvoyer (je pourrais utiliser le passage par adresse mais ce serais utiliser un bazooka pour tuer une mouche à mon sens).

        Aussi la le double pointeur est très utile et presque nécessaire. Néanmoins je te remercie, mais à savoir que le code n'est pas parfait, j'ai pas encore sécurisé le pointeur.

        Par exemple. Si le realloc échoue (ou le malloc, mais j'ai réussis à m'en passer depuis quelques minutes) je n'aurais pas libérer l'espace mémoire et j'aurais perdu le seul accès qui me permettais de le faire.

        Juste ce que je ne comprend pas c'est la dépassement mémoire. Pourtant je m'assure bien d'agrandir petit à petit l'espace allouer et encore plus étrange, c'est que c'est au moment du stockage du troisième caractère (à la ligne 22) que le dépassement intervient. Pourtant le test pour savoir si le realloc a fonctionner passe. Ducoup je ne comprend vraiment plus...

        • Partager sur Facebook
        • Partager sur Twitter
        printf("Les rudiments de la programmation ? Nan mais Hello quoi !");
        Anonyme
          9 août 2017 à 23:07:56

          Ah oui tu as tout à fait raison pour realloc (il faut dire que j'avais oublié cette subtilité, je n'ai jamais vraiment utilisé realloc jusque là), il faut utiliser un autre pointeur déclarer localement pour récupérer le retour le temps de verifier si ça a marché ou pas, et en cas d'échec gérer l'erreur (par exemple avec free).

          Non je pense que le retour par adresse de nbObjets est la meilleure solution, plus une tapette à mouche qu'un bazooca pour le coup, les pointeurs sur pointeurs c'est vraiment le bordel, un simple passage par adresse pour les éviter est un bien moindre prix à payer.

          Concernant ton problème toute de même, je me demande si tu ne devrais pas remplacer :

          *objects[nbObjects - 1] = car;

          Par :

          (*objects)[nbObjects - 1] = car;

          Quand je dis que les pointeurs sur pointeurs c'est vraiment la peste c'est aussi parce que parfois une parenthes en moins et pouf, plus rien.

          Dans les faits ça se gère, mais VRAIMENT, il vaut mieux éviter quand on peut pour diminuer le risque de crash.

          -
          Edité par Anonyme 9 août 2017 à 23:19:19

          • Partager sur Facebook
          • Partager sur Twitter
            9 août 2017 à 23:24:37

            Malheureusement j'ai essayer ta solution et rien n'y fais...


            Pour des raison pratique je choisis de renvoyer le nombre d'objets plutôt que le pointeur. Puisque de toute manière, je ne pourrais pas y échapper éternellement et je dois donc essayer de trouve la solution maintenant.

            Mais l'idée est bonne je la garde en tête.

            En revanche je vais remettre mon code, car il a bien changer depuis :

            // Get all objects in map file
            while (car != EOF)
            {
                if ((car != '\n') && (car != '\r'))
                {
                    nbObjects++;
                
                    inter_objects = (char*) realloc(*objects, nbObjects);
            
                    // Securing the pointer
                    if ((inter_objects == NULL))
                    {
            	    free(*objects);
            	    error("The memory allocation has failed", false);
                    }
            
                    *objects = inter_objects;
            
                    **(objects + (nbObjects - 1)) = car;
                }
            
                car = fgetc(map_file);
            }



            • Partager sur Facebook
            • Partager sur Twitter
            printf("Les rudiments de la programmation ? Nan mais Hello quoi !");
              9 août 2017 à 23:37:46

              Hello,

              • Déjà, on ne cast pas les malloc() / realloc() / calloc() en C.
              • Ensuite, ligne 14: realloc() prend le pointeur à réallouer comme premier argument, pas le contenu de ce pointeur
              • Enfin, pour peu qu'on ait convenablement lu le manuel au sujet de realloc(), on peut se passer du test ligne 8: si le pointeur passé à realloc() est NULL, alors realloc() se comporte comme malloc()...

              -
              Edité par edgarjacobs 9 août 2017 à 23:46:03

              • Partager sur Facebook
              • Partager sur Twitter

              On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

              Anonyme
                9 août 2017 à 23:46:21

                Object a-t'il été correctement initialisé avant l'appel à realloc ? Soit à NULL soit à une adresse allouée.

                nbObjects a-t'il une valeur initiale cohérente ? À savoir le nombre d'éléments du tableau et non pas la position du dernier.

                Je dirais plutôt :

                *(*objects + (nbObjects-1))=car ;

                edgarjacobs : toi tu lis d'une oreille

                -
                Edité par Anonyme 9 août 2017 à 23:49:10

                • Partager sur Facebook
                • Partager sur Twitter
                  9 août 2017 à 23:47:33

                  edgarjacobs a écrit:

                  Hello,

                  • Déjà, on ne cast pas les malloc() / realloc() / calloc() en C.
                  • Ensuite, ligne 14: realloc prend le pointeur à réallouer comme premier argument, pas l' adresse de ce pointeur
                  • Enfin, pour peu qu'on ait convenablement lu le manuel au sujet de realloc(), on peut se passer du test ligne 8: si le pointeur passé à realloc() est NULL, alors realloc() se comporte comme malloc()...

                  Pour les malloc / realloc / calloc en effet j'ai vu que malgrés tous sa fonctionnais mais si tu me dis qu'on ne le fais en C je me pencherais pour savoir si oui ou non c'est accepter dans une des normes C (je compile en C11).

                  En revanche pour le realloc et le premier argument, c'est ce que je fais, je passe le pointeur (d’où la première étoile) et non l'adresse (alors il ne faudrait pas mettre d'étoile). Et dans le cas ou je ne mettrais pas d'étoile j'ai le droit à un : "Invalid pointer".
                  Et avec les 2 étoiles, sa équivaut à lui donner un char en argument.

                  Du coup si je ne vois pas la solution, serais-t'il possible de me l'indiquer s'il te plaît ? :)

                  Pour le dernier point, le code a été modifié dans mon dernier post. Donc plus de soucis à ce niveau la.


                  • Partager sur Facebook
                  • Partager sur Twitter
                  printf("Les rudiments de la programmation ? Nan mais Hello quoi !");
                    9 août 2017 à 23:48:44

                    Désolé, j'ai fais une erreur. Relis mon post, je l'ai modifié.

                    Et si tu montrais les déclarations et la manière d'appeler la fonction, cela faciliterait les réponses.

                    -
                    Edité par edgarjacobs 9 août 2017 à 23:49:49

                    • Partager sur Facebook
                    • Partager sur Twitter

                    On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                      9 août 2017 à 23:50:47

                      PitchPitch a écrit:

                      Object a-t'il été correctement initialisé avant l'appel à realloc ? Soit à NULL soit à une adresse allouée.

                      nbObjects a-t'il une valeur initiale cohérente ? À savoir le nombre d'éléments du tableau et non pas la position du dernier.

                      Je dirais plutôt :

                      *(*objects + (nbObjects-1))=car ;


                      objects a la valeur NULL avant d'entrer dans la fonction et n'est modifier que dans cette boucle.

                      Pour ce qui est de nbObjects il a une valeur initiale de 0. Et est incrémenter à chaque tour de boucle (si le caractère n'est ni un retour ligne/retour chariot ni 'EOF'). Donc de toute évidence je dirais que oui. Pour un fichier contenant '0123456789' il fait respectivement : '1, 2, 3, 4, 5, 6, 7, 8, 9, 10'.

                      En théorie (je dis bien en théorie) tous va bien jusqu'au troisième caractère.

                      Voici l'appel de la fonction :
                      // Appel de la fonction :
                      // ----------------------
                      
                      char *objects = NULL;
                      nbObj = loadMap("Test", &objects);
                      

                      Et voici la fonction au complet :
                      /*
                       * Charge tous les objets de la scène à partir d'un fichier et  renvoie le nombre de ceux-ci.
                       *
                       * @param char filename[] Nom du fichier
                       * @param char **objects  Liste d'objets pour le stockage
                       *
                       * @return int Nombre d'objets charger
                       */
                      int loadMap(char filename[], char **objects)
                      {
                          char *inter_objects = NULL;
                          FILE* map_file = NULL;
                          int nbObjects = 0;
                          char car;
                      
                          map_file = fopen(filename, "r");
                      
                          if (map_file == NULL)
                          {
                      	fprintf(stderr, "The file '%s' was not found\n", filename);
                      	exit(EXIT_FAILURE);
                          }
                      
                          car = fgetc(map_file);
                      
                          // Get all objects in map file
                          while (car != EOF)
                          {
                              if ((car != '\n') && (car != '\r'))
                              {
                                  nbObjects++;
                          
                                  inter_objects = (char*) realloc(*objects, nbObjects);
                      
                                  if ((inter_objects == NULL))
                                  {
                      	        free(*objects);
                      	        error("The memory allocation has failed", false);
                                  }
                      
                                  *objects = inter_objects;
                      
                                  **(objects + (nbObjects - 1)) = car;
                              }
                      
                              car = fgetc(map_file);
                          }
                      
                          fclose(map_file);
                      
                          if (*objects == NULL && (nbObjects != 0))
                          {
                      	error("The memory allocation has failed", false);
                          }
                      
                          return nbObjects;
                      }


                      -
                      Edité par peridot69 9 août 2017 à 23:56:59

                      • Partager sur Facebook
                      • Partager sur Twitter
                      printf("Les rudiments de la programmation ? Nan mais Hello quoi !");
                      Anonyme
                        9 août 2017 à 23:54:00

                        Tu as essayé ce que je t'ai proposé à la fin de mon message ?

                        N'hésite pas à utiliser le debugger pour identifier LA ligne qui pose problème.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          10 août 2017 à 0:00:05

                          Je travail avec VIM et un Makefile. Du coup je n'utilise pas de Point d'arrêts (Si c'est ceux à quoi tu fais référence ?).

                          Bon bah du coup, je vous prie tous de m'excuser, la solution de PitchPitch fonctionne, en effet, la syntaxe :

                          *(*(objects + (nbObjects - 1)) = car;

                          fonctionne très bien. Elle a réussi à résoudre mon problème.

                          Hormis l'affichage qui du coup n'étais pas bon à cause du manque de '\0'. Tous est régler à présent.

                          Je vous remercie tous vraiment ! :D

                          -
                          Edité par peridot69 10 août 2017 à 0:08:13

                          • Partager sur Facebook
                          • Partager sur Twitter
                          printf("Les rudiments de la programmation ? Nan mais Hello quoi !");
                            10 août 2017 à 0:09:31

                            Re,

                            Il me semble que l'erreur se trouve ligne 43, dernier code. J'aurais écrit

                            *objects[nbObjects - 1] = car;
                            
                            // ce qui peut se traduire par - mais est beaucoup moins lisible -
                            
                            *(*objects + nbObjects - 1) = car;

                            -
                            Edité par edgarjacobs 10 août 2017 à 0:10:56

                            • Partager sur Facebook
                            • Partager sur Twitter

                            On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                              10 août 2017 à 0:10:41

                              edgarjacobs a écrit:

                              Re,

                              Il me semble que l'erreur se trouve ligne 43, dernier code. J'aurais écrit

                              *objects[nbObjects - 1] = car;
                              
                              // ce qui se traduit par
                              
                              *(*objects + nbObjects - 1) = car;

                              En effet, je l'ai tester et sa fonctionne très bien :)
                              • Partager sur Facebook
                              • Partager sur Twitter
                              printf("Les rudiments de la programmation ? Nan mais Hello quoi !");
                              Anonyme
                                10 août 2017 à 0:16:27

                                Eeeeg ! C'est ce que j'ai proposé plus haut, tu as mal recopié (pourquoi tu as ajouté des parenthèses ?) ! Boulet va ! Je me tue à t'aider et tu te trompes quand je donne la solution ! ;)

                                Bref, n'oublie pas de passer le sujet en résolu.

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  10 août 2017 à 0:17:56

                                  En effet, pour sa que j'ai adresser des excuses (et pas avec un pointeur :lol:).

                                  Je te remercie encore une fois, je passe en résolu.

                                  Bonne soirée ! ;)

                                  -
                                  Edité par peridot69 10 août 2017 à 0:18:08

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  printf("Les rudiments de la programmation ? Nan mais Hello quoi !");
                                    10 août 2017 à 0:41:23

                                    Hello, il s'en suivra quelques remarques non détaillées qui nécéssitera quelques recherches sur Internet comme complément  :

                                    FILE* map_file = NULL;
                                                   ~~~~~~
                                                   ^ useless !
                                    map_file = fopen(filename, "r");

                                    Initialiser une variable alors qu'elle se voit changer de valeur juste après est une perte de temps.

                                    FILE* map_file;
                                    map_file = fopen(filename, "r");
                                     
                                    if (map_file == NULL)
                                    {
                                        ...
                                    }
                                    char car;
                                    car = fgetc(map_file);

                                    Déclarer ses variables au moment où on en a vraiment besoin est un gain de temps, et lisibilité.

                                    int fgetc(FILE *stream);
                                    ~~~
                                    ^ to ensure that EOF can be represent

                                    La fonction fgetc() retourne un int.

                                    inter_objects = (char*) realloc(*objects, nbObjects);
                                                    ~~~~~~~
                                                    ^ obselete manner

                                    On ne cast plus les retours des fonctions de memory management.

                                    nbObjects++;
                                    inter_objects = (char*) realloc(*objects, nbObjects);
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                    ^ for christ's sake ! It's so slow... allow several byte in one go and resize if you want to O_o.

                                    Allouer byte par byte, c'est lent.

                                    -
                                    Edité par DiscorverYourboringlife 10 août 2017 à 0:41:56

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      10 août 2017 à 23:27:17

                                      DiscorverYourboringlife a écrit:

                                      Hello, il s'en suivra quelques remarques non détaillées qui nécéssitera quelques recherches sur Internet comme complément  :

                                      FILE* map_file = NULL;
                                                     ~~~~~~
                                                     ^ useless !
                                      map_file = fopen(filename, "r");

                                      Initialiser une variable alors qu'elle se voit changer de valeur juste après est une perte de temps.

                                      FILE* map_file;
                                      map_file = fopen(filename, "r");
                                       
                                      if (map_file == NULL)
                                      {
                                          ...
                                      }
                                      char car;
                                      car = fgetc(map_file);

                                      Déclarer ses variables au moment où on en a vraiment besoin est un gain de temps, et lisibilité.

                                      int fgetc(FILE *stream);
                                      ~~~
                                      ^ to ensure that EOF can be represent

                                      La fonction fgetc() retourne un int.

                                      inter_objects = (char*) realloc(*objects, nbObjects);
                                                      ~~~~~~~
                                                      ^ obselete manner

                                      On ne cast plus les retours des fonctions de memory management.

                                      nbObjects++;
                                      inter_objects = (char*) realloc(*objects, nbObjects);
                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                      ^ for christ's sake ! It's so slow... allow several byte in one go and resize if you want to O_o.

                                      Allouer byte par byte, c'est lent.

                                      -
                                      Edité par DiscorverYourboringlife il y a environ 22 heures


                                      En effet je suis d'accord sur tous les points (Sauf sur certains mais c'est plutôt une question de goût, notamment l'endroit ou l'on choisis de déclarer les variables).

                                      En revanche, je ne comprend pas pourquoi allouer byte par byte est lent. Je veux dire, dans mon cas, je ne sais pas à l'avance combien de byte je vais devoir allouer.
                                      Ce serais à tester, mais parcourir tous le fichier pour compter le nombre de caractère, allouer tous les bytes d'un coup, puis ensuite revenir au début du fichier, le reparcourir puis les stocker. Je pense que en terme de performance on gagne pas des masses (pour peu qu'on en gagne). Surtout si le fichier fais des milliers voir des centaines de milliers de caractères.

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                      printf("Les rudiments de la programmation ? Nan mais Hello quoi !");
                                        10 août 2017 à 23:47:15

                                        peridot69 a écrit:

                                        En revanche, je ne comprend pas pourquoi allouer byte par byte est lent. Je veux dire, dans mon cas, je ne sais pas à l'avance combien de byte je vais devoir allouer.
                                        Ce serais à tester, mais parcourir tous le fichier pour compter le nombre de caractère, allouer tous les bytes d'un coup, puis ensuite revenir au début du fichier, le reparcourir puis les stocker. Je pense que en terme de performance on gagne pas des masses (pour peu qu'on en gagne). Surtout si le fichier fais des milliers voir des centaines de milliers de caractères.

                                        Non, je ne fais pas référence à cette méthode. Mais à une autre qui serait ( toujours en ne parcourant qu'une fois le fichier ) d'allouer plusieurs bytes d'un coup ( admettons 16 bytes ), jusqu'à atteindre la fin puis de redimensionner si nécessaire. Tiens, un code source illustrant mes propos. ( Surement pas parfait, mais fonctionnel )

                                        void* fully_projection (FILE* stream, size_t* si)
                                        {
                                        #define OPT_PAGE 16
                                          void* buf;
                                          
                                          if (!(buf = malloc(OPT_PAGE)))
                                            {
                                              return NULL;
                                            }
                                          
                                          size_t si_buf = OPT_PAGE;
                                          size_t rest;
                                          void* buf_cpy = buf;
                                          
                                          do
                                            {
                                              if ((rest = fread(buf, 1, OPT_PAGE, stream)) < OPT_PAGE)
                                        	{
                                        	  if (feof(stream))
                                        	    {
                                        	      *si = si_buf - OPT_PAGE + rest;
                                        	      if (!(buf_cpy = realloc(buf_cpy, *si)))
                                        		{
                                        		  break;
                                        		}
                                        	      return buf_cpy;
                                        	    }
                                        	  break;
                                        	}
                                              si_buf += OPT_PAGE;
                                              if (!(buf_cpy = realloc(buf_cpy, si_buf)))
                                        	{
                                        	  break;
                                        	}
                                              buf = buf_cpy + si_buf - OPT_PAGE;
                                            }
                                          while (1);
                                          
                                          free(buf);
                                          return NULL;
                                        #undef OPT_PAGE
                                        }

                                         ( désolé pour les accolades, l'éditeur refuse de faire ça correctement :s )

                                        -
                                        Edité par DiscoverWhatiam 10 août 2017 à 23:51:27

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          11 août 2017 à 11:16:18

                                          Ah d'accord je vois, l'idée c'est de gagner un peu de temps pour au final redimensionner une seule fois à la fin.

                                          En effet, je n'avais pas penser à sa, je te remercie, je tacherais de l'appliquer les prochaines fois.

                                          Bonne journée. ;)
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                          printf("Les rudiments de la programmation ? Nan mais Hello quoi !");
                                            11 août 2017 à 11:37:25

                                            DiscorverYourboringlife a écrit:

                                            Hello, il s'en suivra quelques remarques non détaillées qui nécéssitera quelques recherches sur Internet comme complément  :

                                            FILE* map_file = NULL;
                                                           ~~~~~~
                                                           ^ useless !
                                            map_file = fopen(filename, "r");

                                            Initialiser une variable alors qu'elle se voit changer de valeur juste après est une perte de temps.

                                            FILE* map_file;
                                            map_file = fopen(filename, "r");
                                             
                                            if (map_file == NULL)
                                            {
                                                ...
                                            }
                                            char car;
                                            car = fgetc(map_file);

                                            Déclarer ses variables au moment où on en a vraiment besoin est un gain de temps, et lisibilité.

                                            int fgetc(FILE *stream);
                                            ~~~
                                            ^ to ensure that EOF can be represent

                                            La fonction fgetc() retourne un int.

                                            inter_objects = (char*) realloc(*objects, nbObjects);
                                                            ~~~~~~~
                                                            ^ obselete manner

                                            On ne cast plus les retours des fonctions de memory management.

                                            nbObjects++;
                                            inter_objects = (char*) realloc(*objects, nbObjects);
                                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                            ^ for christ's sake ! It's so slow... allow several byte in one go and resize if you want to O_o.

                                            Allouer byte par byte, c'est lent.

                                            -
                                            Edité par DiscorverYourboringlife hier à 0:41

                                            Etant en C11, je ne penses pas qu'il puisse déclarer ses variables au moment où il en a besoin, mais forcément au début. D'expérience je dirais que c'est à partir de C99 que l'on peut faire ça.

                                            Pour les fonctions d'allocation mémoire, je suis obligé de caster les fonctions sous peine d'avoir des erreurs du style: impossible de convertir de "void*" en ...

                                            Du coup, comment tu fais pour ne pas faire de cast. Ca m'intéresse parcque c'est bête d'utiliser une fonction standart pas correctement ???

                                            • Partager sur Facebook
                                            • Partager sur Twitter

                                            Plus j'apprends et plus je me rends compte que je ne sais rien.

                                              11 août 2017 à 11:54:54

                                              quent34 a écrit:

                                              Etant en C11, je ne penses pas qu'il puisse déclarer ses variables au moment où il en a besoin, mais forcément au début. D'expérience je dirais que c'est à partir de C99 que l'on peut faire ça.

                                              Mais au bout d'un moment, il faut se mettre à jour. Un tant soit peu ton compilateur est à jour, il devrait compiler automatiquement en c11 ou gnu11.

                                              quent34 a écrit:

                                              Pour les fonctions d'allocation mémoire, je suis obligé de caster les fonctions sous peine d'avoir des erreurs du style: impossible de convertir de "void*" en ...

                                              Du coup, comment tu fais pour ne pas faire de cast. Ca m'intéresse parcque c'est bête d'utiliser une fonction standart pas correctement ???

                                              Il nous faudrait plus d'information, du style : le compilateur utilisé, la version de ce compilateur, ta ligne de commande pour compiler, et éventuellement un code source démontrant l'erreur émisse, avec celle-ci.

                                              -
                                              Edité par DiscoverThenewhorizon 11 août 2017 à 11:55:59

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                11 août 2017 à 11:59:26

                                                quent34 a écrit:

                                                Pour les fonctions d'allocation mémoire, je suis obligé de caster les fonctions sous peine d'avoir des erreurs du style: impossible de convertir de "void*" en ...

                                                A mon avis, tu compiles en C++: l'extension de tes fichiers sources n'est pas .C, mais .CPP

                                                -
                                                Edité par edgarjacobs 11 août 2017 à 11:59:51

                                                • Partager sur Facebook
                                                • Partager sur Twitter

                                                On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                                                  11 août 2017 à 12:30:02

                                                  quent34,

                                                  Le cast de la fonction malloc/realloc n'est pas nécessaire car elle renvoie un pointeur sur void. Et en C la conversion est faite automatiquement vers le type de variables qui récupère ce pointeur void.

                                                  // Pas besoin de cast, C comprend qu'il doit renvoyer vers un type int
                                                  int test = malloc(4);

                                                  En revanche, bien qu'il ne soit pas obligatoire de caster, il peut être utile de le faire pour au moins 2 raison :

                                                  1 - Pour garder une compatibilité avec les compilateurs plus anciens (qui eux n'autorisais pas la conversion implicite?)

                                                  2 - Car cela rend le code compatible avec C++

                                                  Ce sont les 2 principaux arguments que j'ai trouver.

                                                  J'ai aussi entendu parler du fait que le cast peut cacher une erreur au compilateur. Notament si on inclut pas stdlib.h ou malloc.h.
                                                  Mais c'est assez flou. Certains considère qu'ici la véritable erreur c'est l'oublie de l'inclusion de ses fichiers et donc qu'on devrais caster malgré tous si on le désire, d'autres sont contre.

                                                  Ce qui est sur c'est que cette question a des partisans des 2 côtés. Et je pense que on ne peut reprocher catégoriquement à quelqu'un d'utiliser l'une ou l'autre méthode.

                                                  Personnellement je compile toujours autant que possible en version c11.

                                                  -
                                                  Edité par peridot69 11 août 2017 à 12:39:20

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                  printf("Les rudiments de la programmation ? Nan mais Hello quoi !");
                                                    11 août 2017 à 13:09:30

                                                    peridot69 a écrit:

                                                    1 - Pour garder une compatibilité avec les compilateurs plus anciens (qui eux n'autorisais pas la conversion implicite?)

                                                    Non, qui ceux ne supportent qu'une version antérieur du C standard où le type void* n'existait pas.

                                                    -
                                                    Edité par DiscoverMymind 11 août 2017 à 13:42:48

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      11 août 2017 à 13:17:56

                                                      Ah d'accord, j'avais trouver les termes "Compilateurs pré-ANSI" je suppose que sa voulais dire sa.
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                      printf("Les rudiments de la programmation ? Nan mais Hello quoi !");
                                                        15 août 2017 à 10:10:55

                                                        Oui en fait j'ai compris. Comme je travaille sur visual studio je suis en C++. J'avais oublié ce détail :).

                                                        J'ai forcé la compilation en C sur visual et effectivement pas besoin de cast. 

                                                        Par la même occasion si y en a qui savent comment connaître la version du compilateur C que j'utilise avec visual merci d'avance (il me semble que c'est C90 ???).

                                                        -
                                                        Edité par Sylabio 15 août 2017 à 10:39:29

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter

                                                        Plus j'apprends et plus je me rends compte que je ne sais rien.

                                                          15 août 2017 à 11:05:32

                                                          quent34 a écrit:

                                                          Par la même occasion si y en a qui savent comment connaître la version du compilateur C que j'utilise avec visual merci d'avance (il me semble que c'est C90 ???).

                                                          La version du compilateur et la version du standard n'ont rien à voir.

                                                          Sinon pour savoir avec quelle version du standard compile par défaut ton compilateur, il faut lire sa doc. ( Bien sûr dans la version du compilateur utilisé. )

                                                          Par exemple gcc 7.x compile par défaut avec le standard gnu11.

                                                          -
                                                          Edité par GnuAs__ 15 août 2017 à 11:14:19

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            15 août 2017 à 13:02:44

                                                            GnuAs__ a écrit:

                                                            quent34 a écrit:

                                                            Par la même occasion si y en a qui savent comment connaître la version du compilateur C que j'utilise avec visual merci d'avance (il me semble que c'est C90 ???).

                                                            La version du compilateur et la version du standard n'ont rien à voir.

                                                            Sinon pour savoir avec quelle version du standard compile par défaut ton compilateur, il faut lire sa doc. ( Bien sûr dans la version du compilateur utilisé. )

                                                            Par exemple gcc 7.x compile par défaut avec le standard gnu11.

                                                            -
                                                            Edité par GnuAs__ il y a environ 1 heure

                                                            Oui effectivement. C'était du standard dont je voulais parler et non du compilateur. Bon du coup j'ai cherché une doc pour visual studio 2015 visual C++ mais j'ai pas trouvé de doc pdf, c'est bizarre.

                                                            En tout cas sur le site MSDN (que je déteste car je trouve qu'il est mal fait) on trouve pas grand chose sur le standard C utilisé puisque l'on trouve surtout des infos pour le C++.

                                                            La seule chose que j'ai trouvé d'intéressant c'est ça (à ce lien https://msdn.microsoft.com/fr-fr/library/hh409293.aspx#BK_CRT ) :

                                                            "Conformité à la bibliothèque C99 Visual Studio 2015 Implémentation totale de la bibliothèque standard C99, à l'exception de toutes les fonctionnalités de la bibliothèque qui dépendent de fonctionnalités du compilateur non encore prises en charge par le compilateur Visual C++ (par exemple, <tgmath.h> n'est pas implémentée)."

                                                            Bon il semblerait que du coup le compilateur de visual n'est pas conforme au standard C11. 

                                                            Je fais ma petite pub au passage en conseillant de vous procurer visual studio community (100% gratuit) qui reste quoi que l'on puisse dire un très bon IDE, le meilleur pour ce qui est du debug je pense (l'interface du logiciel est quand même mieux que Code:Blocks :) ).

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter

                                                            Plus j'apprends et plus je me rends compte que je ne sais rien.

                                                              15 août 2017 à 13:36:37

                                                              Personnellement je préfére mes outils séparés, éditeur, compilateur, débogueurs tous ça en ligne de commande. Les IDE's je trouve qu'ils font trop usine à gaz.

                                                              -
                                                              Edité par GnuAs__ 15 août 2017 à 13:38:37

                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Erreur de segmentation (realloc - malloc)

                                                              × 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