IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

pb realloc char**


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    339
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 339
    Par défaut pb realloc char**
    salut à tous,

    Je souhaite utiliser (sous linux) l'appel execl définit comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int execv(const char *application, const char * argv[]);
    Comme je dois faire cet appel un nombre important de fois, je le place dans une procédure "iptables_call" à laquelle je transmet les paramètres :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int iptables_call(const char *);
     
    int main()
    {
    ...
    if (iptables_call("-t filter -F")) return(1);
    ...
    }
    Donc le problème c'est que j'ai en entrée une chaîne de caractères séparées par des espaces alors qu'il faut que je transmette une série de chaîne de caractères sans espace. Donc voilà mon idée :
    1) comme la chaîne en entrée est constante, je la copie dans une zone mémoire allouée dynamiquement (variable copied_chain)
    2) Je boucle maintenant sur la longueur de copied_chain et à chaque fois que je trouve un espace :
    a) je remplace l'espace par 0 pour simuler la fin de la chaîne
    b) j'utilise un char ** list_parameters pour le passage de la liste à execl (le 2ème paramètre) et donc quand je tombe sur un espace dans copied_chain, je realloc le char** pour lui dire qu'il y a un pointeur en plus et faire pointer vers le caractère suivant l'espace
    3) je finis par un pointeur NULL pour clotûrer la liste comme préciser dans mes références pour execl
    4) je fais en gros mon appel execl.

    Maintenant voilà le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    int iptables_call(const char *iptables_parameters)
    {
      pid_t pid_son;
      char *copied_chain;
      int long_param, nb_param,i;
      char **list_pointers, **new_list_pointers;
      char *iptables_chain="/sbin/iptables";
      
     // copie de la chaine
      long_param=strlen(iptables_parameters);
      copied_chain=(char *)(malloc(long_param*sizeof(char)));
      if (copied_chain==NULL) {
        fprintf(stderr,"Error : Not enough memory !\n");
        return(1);
      }
      strcpy(copied_chain,iptables_parameters);
     // il faut initialiser la chaine avec "/sbin/iptables" d'abord en sus, et le début de copied_chain
      nb_param=2;
      list_pointers=(char **)(malloc(nb_param*sizeof(char *)));
      if (list_pointers==NULL) {
        fprintf(stderr,"Error : Not enough memory !\n");
        return(1);
      }
      list_pointers[0]=iptables_chain;
      list_pointers[1]=copied_chain;
      i=0;
     //boucle sur la longueur
      while (i<long_param) {
     // test si c'est un espace
        if (copied_chain[i]==' ') {
          copied_chain[i]=0;
          nb_param++;
     // affichage de debogage
          fprintf(stdout,"%s\n",iptables_chain);
     // realloc
          new_list_pointers=(char **)(realloc(list_pointers,nb_param*sizeof(char *)));
     // affichage de debogage
          fprintf(stdout,"%s\n",list_pointers[1]);
          if (new_list_pointers==NULL) {
        fprintf(stderr,"Error : Not enough memory !\n");
        return(1);
          }
          list_pointers=new_list_pointers;
     // initialiser le nouveau pointeur
          list_pointers[nb_param-1]=copied_chain+i+1;
        }
        i++;
      }
     // sortie temporaire en attendant que la chaîne soit bien initialisée
      fprintf(stdout,"ici\n");
      return(1);
       // add NULL at the end
      nb_param++;
      new_list_pointers=(char **)(realloc(list_pointers,nb_param*sizeof(char *)));
      if (new_list_pointers==NULL) {
        fprintf(stderr,"Error : Not enough memory !\n");
        return(1);
      }
      list_pointers=new_list_pointers;
      list_pointers[nb_param-1]=NULL;
     // mise en place de l'appel execl
      pid_son=fork();
      if (pid_son==-1) {
        fprintf(stderr,"Error : New process cannot be created !\n");
        return(1);
      }
      if (!pid_son) {
         /* prototype : int execv(const char *application, const char * argv[]); */
        execv("/sbin/iptables",list_pointers);
      }
      else wait(NULL);
      free(list_pointers);
      free(copied_chain);
      return(0);
    }
    Mon compilateur ne me donne aucune erreur ni warning mais quand je lance le programme, j'ai ça comme affichage :
    /sbin/iptables
    -t
    /sbin/iptables
    *** glibc detected *** free(): invalid next size (normal): 0x0804d030 ***
    Abandon
    Donc sur le premier espace, ça fontionne vu qu'il affiche "-t" mais il bloque sur le deuxième realloc.
    Là j'avoue que je sèche complètement, est-ce que quelqu'un a une idée ? Une simple explication de mon erreur me suffirait.
    Merci d'avance

  2. #2
    Membre éclairé Avatar de je®ome
    Inscrit en
    Octobre 2005
    Messages
    285
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 285
    Par défaut
    Je ne suis pas sûr de ce que j'avance, mais je pense qu0il bloque sur ton free.
    Sinon, tu n'aurais ce message d'erreur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char **list_pointers; 
    free(list_pointers);
    essaies un peu de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     free(*list_pointers);
    ou mets le en commentaire pour tester.

    Comme dis, je ne suis pas sûr ...

  3. #3
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Quelques remarques:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    copied_chain=(char *)(malloc(long_param*sizeof(char)));
    en C devrait être écrit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    copied_chain= malloc(long_param);
    Pas de cast et sizeof(char) vaut 1...

    Pareil pour le realloc...

    Pourquoi utiliser la valeur directement, le code ascii existe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    copied_chain[i] = '\0';
    Sinon, es-tu sûr d'avoir mis les bonnes inclusions pour chaque fonction que tu
    utilises parce ton code fonctionne chez moi...

    [EDIT]
    J'ai mis:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/wait.h>
    [/EDIT]

    Jc

  4. #4
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    339
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 339
    Par défaut
    Je ne suis pas sûr de ce que j'avance, mais je pense qu0il bloque sur ton free
    Il ne bloque pas au niveau du free, il bloque bien avant. D'ailleurs le free dans cette version du programme n'est même pas atteint car il y a un return avant. Merci quand-même

    Sinon, es-tu sûr d'avoir mis les bonnes inclusions pour chaque fonction que tu utilises parce ton code fonctionne chez moi...
    J'ai vérifié mes inclusions et il n'y a que sys/types.h que je n'utilisais pas mais même avec ça ne fonctionne toujours pas...

    Je rajoute quelques précisions au cas où : c'est une partie du programme, il y a une autre partie qui s'occupe au préalable de lire un fichier de confiuration et qui fait donc quelques malloc et realloc. Existerait-il une limite ??? Par contre, ce que je suis sûr c'est que j'ai encore suffisamment de mémoire...
    Mais effectivement, je viens de tester cette partie du programme seule et ça fonctionne... je comprends pas pourquoi j'ai pas un segfault dans ce cas ?

    Bon, à priori mon code est bon donc je réitère ma question : existe-t-il une limite du nombre de malloc/realloc ???

  5. #5
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Citation Envoyé par le mage tophinus
    Bon, à priori mon code est bon donc je réitère ma question : existe-t-il une limite du nombre de malloc/realloc ???
    Non, pas que je sache, pour tester:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #include <stdio.h>
     
    #include <stdlib.h>
     
    int main()
    {
            int i,j;
            char *ptr,*ptr2;
     
            for(i=0;i<10000;i++)
                    {
                    ptr = malloc(2);
     
                    if(ptr==NULL)
                            {
                            printf("Erreur de malloc\n");
                            return 1;
                            }
     
                    for(j=0;j<10000;j++)
                            {
                            ptr2 = realloc(ptr,3+j);
                            if(ptr2==NULL)
                                    {
                                    printf("Erreur de realloc\n");
                                    return 1;
                                    }
                            ptr = ptr2;
                            }
     
                    free(ptr);
                    }
     
            return 0;
    }
    Et ça fonctionne très bien...

    Jc

  6. #6
    Membre émérite Avatar de crocodilex
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    697
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 697
    Par défaut
    Citation Envoyé par fearyourself
    Non, pas que je sache, pour tester:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <stdio.h>
    
    #include <stdlib.h>
    
    int main()
    {
            int i,j;
            char *ptr,*ptr2;
            [...]
                             ptr = ptr;
            [...]
    
            return 0;
    }
    Et ça fonctionne très bien...

    Jc
    Petite erreur de frappe je suppose....

  7. #7
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    339
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 339
    Par défaut
    effectivement, je n'ai pas d'erreur avec ton nouveau code, donc ce n'est pas un problème de nombre de malloc/realloc.

    Dernière question et après je délesterais : Est-ce que j'initialise bien ma chaîne en faisant ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char *iptables_chain="/sbin/iptables";
    Y'a pas besoin d'un malloc ici ??? Parce que je vois que ça à priori...

    [edit]
    même avec la modification de crocodilex, le nouveau code fonctionne toujours
    [/edit]

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème realloc char**
    Par orj30754 dans le forum Débuter
    Réponses: 17
    Dernier message: 03/11/2009, 17h21
  2. Réponses: 3
    Dernier message: 02/07/2003, 16h24
  3. Réponses: 6
    Dernier message: 24/03/2003, 17h11
  4. Traitement d'un char* renvoyé par une DLL en C++
    Par LuluTchab dans le forum Langage
    Réponses: 4
    Dernier message: 22/03/2003, 21h48
  5. Réponses: 4
    Dernier message: 03/12/2002, 16h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo