Compilation en c

Discutez d'informatique ici !
Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

Compilation en c

par Rockleader » 25 Oct 2015, 14:50

Salutation, pourriez vous m'indiquer ce qui ne marche pas dans mon programme.

Le but est de compiler la liste du main paramétré.


Le parallélisme ici n'est pas obligatoire et je dirais même limite inutile, mais c'est dans ma consigne donc on fait avec^^


changerExtension est une fonction qui va faire la conversion de fichier.c à fichier.o dans mon cas.
Le détail de cette fonction se trouve en bas si besoin

Le vrai problème se situe donc sur mon main.
Il semblerait que la première étape fonctionne bien puisque je retrouve bien mes .o.

En revanche la seconde étape semble...ne rien faire tout simplement...même pas de message d'erreur...
Mes erreurs sont supposé s'écrire dans un fichier puisque je fais une redirection.

Code: Tout sélectionner
int main(int argc, char const *argv[])
{
   int nbFich;
   pid_t pid[NB_FICH_MAX];
   int k;
   int err;
   int fd;
   char* arg[NB_FICH_MAX];
   int k3=0;
   if(argc==1){
      Erreur("Nombre d'arguments incorrect",50);
   }else{
      //au moins un fichier à compiler
      nbFich=argc-1;
      //on crée nbFIch fils
      err=dup(2);//save erreur
      close(2);
      if((fd=open("FichierErreur.err",O_WRONLY | O_CREAT,S_IRWXU))==-1){
               Erreur("Ouverture fichier écriture",52);
            }else{
               dup(fd);
               //fd va dans 2
            }
      for(k=0;k<nbFich;k++){
         switch(pid[k]=fork()){
            case -1:
               Erreur("fork",51);
            case 0:
            
                  execlp("cc","cc","-c",argv[k+1],NULL);

            default:
               if(k==(nbFich-1)){//si on est sur le dernier process
                  wait(NULL);
                  //on att que le dernier cc soit effectué
                  int k2;
                  for(k2=0;k2<nbFich;k2++){
                     arg[k3]=changerExtension(argv[k2+1],"o");
                     k3++;
                  }
                  execv("cc",arg);
                  close(fd);
                  dup(err);
               }
         }
      }

   }
   return 0;
}


Si vous voyez ce qui peut causer le soucis...après exécution. Les fichiers .o sont bien là mais je n'ai pas de a.out. Donc la seconde partie ne se fait pas...mais pourtant je n'ai pas d'erreur dans mon fichier d'erreur.


Code: Tout sélectionner
char* changerExtension(const char* fich, const char* extension){
   int k;
   int k2=0;
   int extensionPast=0;
   char* newFile="";
   char* fich2="";
   char* ext2="";
   fich2=  malloc (50 * sizeof(char));
   newFile = malloc (50 * sizeof(char));
   ext2 = malloc (50 * sizeof(char));
   strcat(fich2,fich);
   strcat(ext2,extension);
   for(k=0;k<strlen(fich);k++){
      if(fich2[k]=='.'){
         extensionPast=1;
         newFile[k2]=fich2[k];
         k2++;
      }else{
         if(extensionPast==0){
            newFile[k2]=fich2[k];
            k2++;
         }
      }
   }
   strcat(newFile,ext2);
   return newFile;
}
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !



LeJeu
Membre Irrationnel
Messages: 1141
Enregistré le: 24 Jan 2010, 22:52

par LeJeu » 02 Nov 2015, 10:15

Salut Rock,

Plein de soucis dans ton code ....

1) ton switch n'a pas de break à chaque case , tout va s'enchainer.
2) ton test qui attend que les sous process soient terminés, serait quand même plus proprement fait en dehors de la boucle
3) les sous process qui lance la commande CC , n'ont plus rien à faire ensuite, le mieux serait de faire un exit de suite
4)il manque un NULL final à ton tableau d'arg que tu construis
5) il manque un 0 final au nom de fichier que tu construis ( et on doit pouvoir écrire plus simplement ta fct..)

Ps - le parallélisme, n'est pas idiot dans cet exemple , il permet de compiler tous tes programmes en parallèle puis de les linker quand c'est terminé ( et il faut donc attendre)

joel76
Membre Relatif
Messages: 230
Enregistré le: 11 Fév 2013, 16:31

par joel76 » 02 Nov 2015, 11:53

Une erreur dans le code de la fonction changeant le nom de l'extension : tu fais un malloc de 50 char pour fic2 (pourquoi 50 d'ailleurs) et ensuite un strcat dans fic2.
strcat copie la chaine fournie en deuxième argument A LA FIN de fic2, or malloc n'assure pas que les octets fournis soient mis à 0 donc c'est potentiellement dangereux.
Soit tu fais un strcpy dans fic2, soit tu fais un calloc(50 , sizeof(char)) qui lui assure des octets à zero.
Ensuite tu te compliques gravement la vie : l'extension est par définition ce qui suit le dernier point ('.') du nom du fichier. Il suffit de le repérer par un strrchr(nom_fichier , '.') et ensuite de copier ta nouvelle extension à cet endroit.
pour le calcul de la longueur de la chaine à fournir, c'est un peu fastidieux mais c'est faisable :
- calcul de la longueur de la chaine fournie
- calcul de la longueur de l'ancienne extension (après l'avoir repérée à l'aide du strrchr) attention au point, ne pas effacer !
- calcul de la longueur de la nouvelle extension
- calcul final de la longueur de chaine (sans oublier le 0 final)

joel76
Membre Relatif
Messages: 230
Enregistré le: 11 Fév 2013, 16:31

par joel76 » 02 Nov 2015, 12:26

Je me pose une question : pourquoi changer l'extension des fichier en ".o" ? Ces fichiers ne sont pas créés lors de la compilation ?

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 02 Nov 2015, 15:48

joel76 a écrit:Je me pose une question : pourquoi changer l'extension des fichier en ".o" ? Ces fichiers ne sont pas créés lors de la compilation ?



Ben, lorsque tu fais la compilation le .c crée bien ton .o

Mais après tu as besoin du .o pour faire l'édition de lien.

Je sais bien qu'on peut compiler et faire l'édition de lien directement; mais l'exo n'a aucun sens si on le fais comme ça =)


Sinon, je vérifie que le fichier ait bien un seul dans son nom. Sa me permet de savoir par exemple si j'ai fich.toto.c qu'il y a un problème, je n'ai pas à avoir deux points dans un nom de fichier; c'est pour ça que je regarde char par char.



Le Jeu,

je ne vois pas l'intérêt de faire un exit ou des break à ce moment là.

Si le code se passe bien, tous ce qui suit le exec n'est pas exécuté, et donc le exit ne sert à rien.

Si le code se passe mal, la compilation ne marche pas, et de toute façon le programme s'arrête aussi en écrivant mes erreurs dans le fichiers des erreurs.



Il manque un NULL au tableau d'arg que je construis ? C'est possible, mais j'ai du mal à voir tu l'aurais mis ou ?
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

LeJeu
Membre Irrationnel
Messages: 1141
Enregistré le: 24 Jan 2010, 22:52

par LeJeu » 02 Nov 2015, 17:42

Rockleader a écrit:Ben, lorsque tu fais la compilation le .c crée bien ton .o


Le Jeu,

je ne vois pas l'intérêt de faire un exit ou des break à ce moment là.

Si le code se passe bien, tous ce qui suit le exec n'est pas exécuté, et donc le exit ne sert à rien.

Si le code se passe mal, la compilation ne marche pas, et de toute façon le programme s'arrête aussi en écrivant mes erreurs dans le fichiers des erreurs.

Il manque un NULL au tableau d'arg que je construis ? C'est possible, mais j'ai du mal à voir tu l'aurais mis ou ?



Il est essentiel de mettre un break dans un switch ( sauf cas exeptionnel, que l'on commente clairement dans le code , sinon apres le premier cas tu executes , le second puis le troisième)
=> ici apres le CC tu executes le default .. ce qui n'est absolument pas ce que tu veux

De plus quand tu arrive dans ton fork, il est clair que plus rien dans ton code n'est à exécuter, autant faire 'exit' du process fils

en C il faut tjrs un delimitateur de fin .. tu passes la variable arg à la fct execv, il faut bien qu'elle trouve le nombre de paramètres... donc il faut un null final, cad : arg[k3]= NULL après la boucle de remplissage

Ps ..t'es marrant, ton prgramme ne marche pas, tu demandes de l'aide , et tu rechignes à corriger ...

Joel16 te le dis différemment... mais ta fct de changement d'extention, c'est tout et n'importe quoi, c'est inesthétique, lourd, consommateur de mémoire et buggé ...

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 02 Nov 2015, 20:46

Je ne rechigne pas à corriger, je cherche à comprendre pourquoi je ferais une chose avant de la faire...ce que beaucoup de monde ne fait pas il me semble. Comprendre, puis faire, ce n'est pas la même chose qu'appliquer bêtement une solution que l'on ne comprends pas...alors je sais que je suis un peu lent à la détente, mais si cela te vexe que je n'applique pas directement alors ce n'est pas la peine de venir...


En ce qui concerne ma fonction d'extension, je n'ai jamais prétendu qu'elle était parfaite, encore moins que les arguments de Joel n'étaient pas bons. J'ai simplement expliqué comment j'ai raisonné lorsque je l'ai réalisé. Si je n'ai rien dis de plus là dessus c'est bien parce que j'ai compris les problèmes là dessus et que je vais les modifier. Je ne discute que de ce que je ne comprends pas...

=> ici apres le CC tu executes le default ..


Je veux bien te croire, mais je ne comprends pas pourquoi !


On m'a répété sans cesse que le code qui se situe après une fonction exec est exécuté uniquement en cas d'erreur.

Donc, si et seulement si mon cc marche je ne vais pas rentrer dans le default puisque le default n'existera plus après passage dans le exec non ?

Là, tu semble me suggérer que le exec est limité à la portion de code que tu étudies (le scope si je me trompe pas, fatal ou ampholyte m'en avait parlé il y a quelques temps). Donc dans ce cas au case.


J'ai sûrement tord dans ce que je raconte...mais je veux juste comprendre où est mon erreur...
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 02 Nov 2015, 21:04

retourne aux basiques et apprend la syntaxe du switch.
la vie est une fête :)

LeJeu
Membre Irrationnel
Messages: 1141
Enregistré le: 24 Jan 2010, 22:52

par LeJeu » 02 Nov 2015, 22:32

Rockleader a écrit:Je veux bien te croire, mais je ne comprends pas pourquoi !


le fork, t'embrouille, je pense , oublie le un instant

le
Code: Tout sélectionner
switch( x)

case a:
   je fais ça
   break;
case b:
   je fais ci
   break;   
default:
   je fais donc autre chose



C'est un peu comme un if else :

Code: Tout sélectionner
if ( x==a)
   je fais ça
else if (x == b)
   je fais ci
else
   je fais donc autre chose



sauf que si tu ne mets pas de break ca fait
Code: Tout sélectionner
if ( x==a)
   je fais ça
   je fais ci
   je fais donc autre chose
else if (x == b)
   je fais ci
   je fais donc autre chose
else
   je fais donc autre chose


Donc tu mets les break .... c'est mieux

( même et surtout si tu crois que quelque chose n'est pas possible / pas probable .....
tu verrais le nombre de circonstances où dans un programme ca arrive quand même
=> tu ne préjuges donc pas : tu CODES !)

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 4 invités

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite