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 :

Probleme de mémoire : exec !?


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Par défaut Probleme de mémoire : exec !?
    Bonjour,

    Voilà, je suis en train de faire un minishell en C.
    Je parse mes arguments comme suit :
    un tableau de pointeurs de char qui contient la ligne ("ls truc bidule")
    Un tableau de pointeur de char qui contient les arguments (dans l'exemple "truc bidule").

    Cependant, j'ai des comportements très bizarres, celà me lance certains arguments et pas d'autres, en me mettant des erreurs... étranges !
    Après un valgrind, je constate qu'il me dit, que le 2eme argument contient des bytes non initialisés... mais pourquoi, je n'en sais rien. Il me semble que je fais la démarche necessaire.

    Voici 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
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
     
     
          #include <stdio.h>
          #include <stdlib.h>
          #include <sys/types.h>
          #include <sys/wait.h>
          #include <unistd.h>
          #include <string.h>
          #include <dirent.h>
     
     
          char** parsing(char * str, int x)
          {
                  int cpt=0;
                  char ** tab = NULL;
                  char *pch = strtok(str, " ");
     
                  tab = malloc(1024 * sizeof(char*));
     
                  while(pch != NULL)
                  {
                          if(cpt >= x)
                          {
                                  tab[cpt-x] = malloc (1024);
                                  strcpy(tab[cpt-x], pch);
                                  tab[cpt-x] = pch;
                          }
                          cpt++;
                          pch = strtok (NULL, " ");
                  }
     
                  free(pch);
                  return tab;
          }
     
     
          int comptemot(char * str)
          {
                  int i=0;
                  int nbmot=1;
                  int sizemot = strlen(str);
     
                  for(i = 0 ; i < sizemot; i++)
                  {
                          if(str[i] == ' ')
                                  nbmot++;
                  }
                  return nbmot;
          }
     
    // On vérifie si la commande se situe dans "/bin/", sinon elle est dans "/usr/bin/"
          int verify_cmd(char * cmd)
          {
     
                  struct dirent *dirlist;
                  DIR *rep;
                  rep = opendir("/bin/");
     
                  while ((dirlist = readdir(rep)))
                  {
                          if( dirlist->d_type == DT_REG)
                          {
                                  if(strcmp(dirlist->d_name, cmd) == 0)
                                  {
                                          return 1;
                                  }
                          }
                  }
                  closedir(rep);  
     
                  return 0;
          }
     
     
          void exec_cmd(char *cmd, char** arg)
          {
                  pid_t pid;
                  int status;
                  char *bin=NULL;
                  bin = malloc( 1024 );
     
                  if(verify_cmd(cmd) == 1)
                  {
                          strcpy(bin, "/bin/");
                  }
                  else
                  {
                          strcpy(bin, "/usr/bin");
                  }
     
                  strcat(bin, cmd);
                  printf("arg : %s\n", arg[0]);
     
                  pid = fork();
     
                  switch(pid)
                  {
                          case -1 : perror("problem fork"); break;
     
                          case 0: execv(bin, arg);break;
     
                          default : waitpid(pid, &status, 0);
                  }
                  free(bin);
          }
     
     
     
          int main()
          {
                  char** ligne = NULL;
                  char ** cmd = calloc(1024,1);
                  char chx_user[512];
                  char bis[512];
                  int size;
     
                  while(1)
                  {
                          if (fgets(chx_user, 512, stdin) != NULL)
                          {      
     
                                  size = comptemot(chx_user);
                                  printf("size %d\n", size);
                                  strcpy(bis, chx_user);
     
                                  ligne = parsing(chx_user, 0);
                                  cmd = parsing(bis, 1);
     
                                  exec_cmd(ligne[0], cmd);
     
                                  cmd=memset(cmd, '\0', 1024);
     
                                  free(ligne);
     
                          }
                  }
          }
    Pourriez vous m'indiquer ce qui ne va pas ?
    Ca fait un moment que j'y suis dessus, et je sèche..

    Merci d'avance,

    Bonne journée/soirée !

  2. #2
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Il faut revoir les questions d'allocation dynamique dans ce code, elles sont incohérentes :
    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
    int main()
    {
      char** ligne = NULL;
      char ** cmd = calloc(1024,1);
      ....
      while(1)
      {
         if (fgets(chx_user, 512, stdin) != NULL)
         {      
           ....
           cmd = parsing(bis, 1);
           ....
         }
      }
    }
    1- La valeur obtenue par calloc() pour cmd est écrasée par l'appel à parsing(). A quoi sert alors ce calloc() si ce n'est à faire une fuite mémoire ?
    2- Le 1 dans le calloc() est illogique. On devrait avoir sizeof(char*)

    3- Dans parsing()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if(cpt >= x)
    {
       tab[cpt-x] = malloc (1024);
       strcpy(tab[cpt-x], pch);
       tab[cpt-x] = pch;
    }
    On copie pch dans la chaine allouée par le malloc() et on écrase ensuite l'adresse de cette chaine par l'adresse pch. La chaine allouée est devenue inaccessible.

    4-
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char *pch = strtok(str, " ");
    ....
    while(pch != NULL)
    {
    ....
      pch = strtok (NULL, " ");
    }     
    free(pch);
    le free(pch) est toujours un free(NULL)

  3. #3
    Membre averti
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Par défaut
    Bonjour,

    D'accord pour le calloc, c'était une faute d'inattention, compte tenu du fait que j'avais mis déjà mon autre char ** (ligne) à NULL.

    J'ai appliqué vos conseils pour le reste, ce qui me donne :
    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
     
    char** parsing(char * str, int x)
    {
    	int cpt=0;
     
    	char ** tab = NULL;
    	char *pch = strtok(str, " ");
     
    	tab = malloc(1024 * sizeof(char*));
     
    	while(pch != NULL)
    	{
    		if(cpt >= x)
    		{
    			tab[x-cpt] = malloc(1024 * sizeof(char));
    			strcpy(tab[x-cpt], pch);
    		}
    		cpt++;
    		pch = strtok (NULL, " ");
    	}
    	return tab;
    }
    Idem au début, j'ai simplement mis à NULL cmd:
    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
     
    int main()
    {
      char** ligne = NULL;
      char ** cmd = NULL;
      ....
      while(1)
      {
         if (fgets(chx_user, 512, stdin) != NULL)
         {      
    	size = comptemot(chx_user);
    	strcpy(bis, chx_user);
            cmd = parsing(bis, 1);
            ....
         }
      }
    }

    En revanche, le valgrind me sort toujours des erreurs :
    ==3153== Invalid write of size 4
    ==3153== Invalid read of size 4
    ==3153== Syscall param execve(argv) points to uninitialised byte(s)

    Je comprends ce qu'il me dit. (J'essaye décrire/de lire dans un espace qui ne m'est pas attribué et execve possède des arguments qui pointes sur des bytes non initialisés).

    En revanche, je ne vois pas ce qui me paraît suspect. D'après valgrind, c'est dans ma fonction "parsing".
    J'ai essayé de ne pas mettre malloc, et de mettre NULL à la place dans ma boucle for, rien n'y fait.

    Quelqu'un pourrait il m'aiguiller à ce sujet ?

  4. #4
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if(cpt >= x)
    {
       tab[x-cpt] = malloc(1024 * sizeof(char));
    on a x-cpt <= 0 . Le seul cas où ça ne plante pas est pour x == cpt sinon, l'indice est négatif. Normal ?

  5. #5
    Membre averti
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Par défaut
    Oula oui !
    En le déroulement a la main, j'accède à des indices négatifs, tu as raison.
    Il faudrait faire cpt-x plutot que l'inverse (vu que c'est cpt qui s'incrémente et non x)
    Je vais voir celà, merci

    Edit : Hélas j'ai toujours ce maudit :
    ==5165== Syscall param execve(argv) points to uninitialised byte(s)
    ==5165== Address 0x4198e58 is 8 bytes inside a block of size 4,096 alloc'd (Du au malloc de ma fonction parsing apparement)

  6. #6
    Membre averti
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Par défaut
    Re-bonjour,

    J'ai corrigé toutes mes fuites de mémoire, seulement le probleme que me sort valgrind reste et perdure :
    Citation Envoyé par valgrind
    ==6684== Syscall param execve(argv) points to uninitialised byte(s)
    ==6684== at 0x40DCEFF: execve (execve.c:60)
    ==6684== by 0x405CB55: (below main) (libc-start.c:220)
    ==6684== Address 0x4198e58 is 8 bytes inside a block of size 4,096 alloc'd
    ==6684== at 0x4024C1C: malloc (vg_replace_malloc.c:195)
    ==6684== by 0x80487FB: parsing (/home/monrep/proj)
    ==6684== by 0x8048A9A: main (/home/monrep/proj)
    ==6684==
    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
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <string.h>
    #include <dirent.h>
     
     
    char** parsing(char * str, int x)
    {
    	int cpt=0;
     
    	char ** tab = NULL;
    	char *pch = strtok(str, " ");
     
    	tab = malloc(1024 * sizeof(char*));
     
    	while(pch != NULL)
    	{
    		if(cpt >= x)
    		{
     
    			tab[cpt-x] = malloc(1024 * sizeof(char));
     
    			if(strncmp(pch," ",1) == 0)
    			{
    				printf("la !\n");
    			}
     
    			else
    			{
    				strcpy(tab[cpt-x], pch);
    			}
    		}
    		cpt++;
    		pch = strtok (NULL, " ");
    	}
    	return tab;
    }
     
     
    int comptemot(char * str)
    {
    	int i=0;
    	int nbmot=1;
    	int sizemot = strlen(str)-1;
    	for(i = 0 ; i < sizemot; i++)
    	{
    		if(str[i] == ' ')
    			nbmot++;
    	}
    	return nbmot;
    }
     
    int verify_cmd(char * cmd)
    {
    	struct dirent *dirlist;
    	DIR *rep;
    	rep = opendir("/bin/");
     
     
    	while ((dirlist = readdir(rep))) 
    	{
    		if( dirlist->d_type == DT_REG)
    		{
    			if(strcmp(dirlist->d_name, cmd) == 0)
    			{
    				closedir(rep);  
    				return 1;
    			}
    		}
    	}
     
    	closedir(rep);  
    	return 0;
    }
     
     
    int main()
    {
    	char** ligne = NULL;
    	char ** lst_cmd = NULL;
    	char chx_user[512];
    	char bis[512];
    	int size;
     
     	pid_t pid;
     	int status;
    	int i;
     
    	while(1)
    	{
    		if (fgets(chx_user, 512, stdin) != NULL) 
    		{	
    			chx_user[strlen(chx_user)-1]='\0';
    			size = comptemot(chx_user);
     
    			strcpy(bis, chx_user);
    			ligne = parsing(chx_user, 0);
    			lst_cmd = parsing(bis, 1);
     
     
     
    			char *bin = malloc(1024*sizeof(char));
     
     
    			if(verify_cmd(ligne[0]) == 1)
    			{
    				strcpy(bin, "/bin/");
    			}
    			else
    			{
    				strcpy(bin, "/usr/bin");
    			}
    			strcpy(bin, "/bin/");
    			strcat(bin, ligne[0]);
    			pid = fork();
    			switch(pid)
    			{
    				case -1 : perror("problem fork"); break;
    				case 0: execv(bin, lst_cmd);break;
    				default : waitpid(pid, &status, 0);
    			}		
     
     
    			for(i=0; i < size; i++)
    			{
    				free(ligne[i]);
    			}
    			for(i=0; i < size-1; i++)
    			{
    				free(lst_cmd[i]);
    			}
     
     
    			free(bin);
    			free(lst_cmd);
    			free(ligne);
     
    		}
    	}
    }
    Honnetement je ne vois pas ou ca coince là.
    Si quelqu'un pourrait me dire, car je commence à sècher après tout le temps que j'y ai passé

  7. #7
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2010
    Messages : 21
    Par défaut
    Salut (et au passage merci

    Je viens de relire plusieurs fois ton code, et si je comprends bien, dans ton main, tu utilise "lst_cmd" pour y mettre la liste des arguments de la commande, commande NON comprise.
    Ensuite tu passes ça à execv(), avec "bin" qui est le chemin absolu de la commande.

    Or :
    - si tu utilisait execvp(), tu n'aurai besoin que du nom de la commande en premier argument (le chemin est cherché avec le PATH, et /usr/ et /usr/bin/ y sont par défaut), et du coup ça permettrait d'enlever ta fonction verify_cmd(),
    - la fonction execv() (et execvp()) attend en 2ème position la liste des arguments, INCLUANT le nom de la commande. Donc oui ça fait un peu doublon avec le premier argument de execv(), mais c'est comme ça ;-)


    C'est tout ce que j'ai vu pour l'instant, mais je regarderais encore demain ^^

  8. #8
    Membre averti
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Par défaut
    Yes tout à fait pour "lst_cmd", j'ai constaté ca dans la soirée, j'ai viré et j'ai mis "ligne" à la place

    Pour l'execvp je ne savais pas, merci du tuyau !

    Maintenant ca fonctionne niquel le minishell

Discussions similaires

  1. probleme de mémoire
    Par beLz dans le forum C
    Réponses: 6
    Dernier message: 10/07/2007, 21h05
  2. probleme de mémoire : Java heap space
    Par Seb33300 dans le forum Interfaces Graphiques en Java
    Réponses: 10
    Dernier message: 21/02/2007, 13h40
  3. Réponses: 1
    Dernier message: 16/01/2007, 10h21
  4. Probleme de mémoire avec FireBird
    Par NicolasR dans le forum Bases de données
    Réponses: 2
    Dernier message: 19/05/2006, 16h28
  5. [VBscript] probleme avec shell.exec
    Par eown dans le forum Windows
    Réponses: 1
    Dernier message: 23/04/2006, 09h24

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