2010-09-21 4 views
1

J'ai un programme shell personnalisé dans lequel j'ai inclus signal.h, unistd.h et stdio.h. Je travaillais à l'origine sur RedHat Enterprise (je ne sais pas exactement quelle version, mais pas trop vieille) et j'ai pu utiliser gcc sur mon programme et il a bien compilé et s'est bien passé. Maintenant, je l'ai déplacé vers Ubuntu et gcc me donne quelques erreurs, dont la première est conflicting types for 'getline()'. D'autres erreurs indiquent incompatible implicit declaration of built-in function strlen. J'ai remplacé les fonctions en question, pourquoi cela fonctionnait-il dans RedHat mais pas dans Ubuntu? Linux n'est pas mon truc, alors s'il vous plaît, parlez clairement. Faites-moi savoir si vous avez besoin de plus de détails sur les erreurs.Erreurs avec gcc lors de la compilation du programme C

/* define a global input buffer */ 
#include <signal.h> 
#include <unistd.h> 
#include <stdio.h> 

#define MAXARG 512 
#define MAXBUF 512 
#define BUFFER_SIZE 50 
#define MAX_COMMANDS 10 
char buffer [BUFFER_SIZE]; 
static char *prompt = "MYSHELL>"; 
static char inpbuf[MAXBUF]; 
static char *arg[MAXARG+1]; 
static char tokbuf[2*MAXBUF]; 
static char *tok = tokbuf; 
char history[MAX_COMMANDS][MAXBUF]; 
int cmd_num; 

void getline(void); 

void getline() { 
int length; 

length = read(0, inpbuf, MAXBUF); 
if (length == 0) { 
    printf("\n"); 
    exit(0); 
} 
inpbuf[length] = '\0'; 

} 

void processline() { 
char *ptr = inpbuf; 
int narg; 
for (narg=0;;) {  
    arg[narg] = tok; 
    for (; *ptr == ' ' || *ptr == '\t'; ptr++) 
     ; 
    while(*ptr != ' ' && *ptr != '\t' && *ptr != '\n' && 
      *ptr != '\0' && *ptr != ';' && *ptr != '&') 
     *tok++ = *ptr++; 
    *tok++ = '\0'; 
    if (narg < MAXARG) 
     narg++; 
    if (*ptr == '\n') 
     break; 
} 
// clear the input buffer 
for (ptr = inpbuf; *ptr != '\n'; ptr++) 
    *ptr = ' '; 
if (narg != 0) { 
    arg[narg] = NULL; 
} 
} 

void handle_SIGINT() 
{ 
write(STDOUT_FILENO, buffer, strlen(buffer)); 
} 

int main() 
{ 
    int pid, exitstat, ret; 
    struct sigaction handler; 
    handler.sa_handler = handle_SIGINT; 
    handler.sa_flags = 0; 
    sigemptyset(&handler.sa_mask); 
    sigaction(SIGINT, &handler, NULL); 
    strcpy(buffer, "Caught Control C\n"); 

    while (1) { 
     printf("%s ", prompt); 
     fflush(stdout); 
     getline(); 
     processline(); 
     if ((pid = fork()) < 0){ 
      fprintf(stderr, "myshell: error\n"); 
      return (-1); 
     } 

     if (pid == 0) { 
      execvp(*arg, arg); 
      fprintf(stderr, "%s\n", *arg); 
      exit(127); 
     } 
     waitpid(pid, &exitstat, 0); 
    } 
    return 0; 
} 
+4

Il serait très utile pour vous d'essayer de réduire le programme à un exemple minimal qui démontre le problème. Continuez à supprimer tout votre code jusqu'à ce que vous ayez juste les inclusions et les déclarations (et peut-être un "bonjour, monde") qui démontre le problème. Cela peut vous aider à trouver le problème, mais si ce n'est pas le cas, vous pouvez éditer votre question et l'afficher ici, ce qui nous aidera à trouver votre problème. –

+1

Le contenu du fichier d'en-tête peut varier d'un système à l'autre et de la compilation du compilateur à la compilation du compilateur et entre les bibliothèques. Vous pouvez trouver la sortie de 'gcc -E' très éclairante. Et ce que Brian Campbell a dit. – msw

+0

Oui, évidemment ce que Brain a dit, mais j'essaie d'éviter de "supprimer" le code pour trouver le problème. Cela a fonctionné sur un autre système et même si je me rends compte que les compilateurs varient d'un système à l'autre, j'espérais que c'était quelque chose de simple que quelqu'un puisse répondre directement de la tête. – ubiquibacon

Répondre

4

solution simple serait de renommer votre fonction getline(), par exemple à my_getline()

+1

Cela a permis de se débarrasser de la plupart de mes erreurs, mais je me demande pourquoi 'gcc' sur RedHat m'a permis de remplacer ces fonctions, mais' gcc' sur Ubuntu n'a pas ... Cela me semble étrange. – ubiquibacon

4

incompatible implicit declaration of built-in function strlen

Inclure <string.h>

conflicting types for 'getline()

<stdio.h> contient déjà une déclaration de getline, alors assurez-vous que nulle part dans votre code que vous avez redéclarée/redéfini getline() [avec un prototype différent ]

+1

J'ai eu un prototype (par ANSI C) pour getline, et plusieurs autres fonctions (qui sont déclarées dans 'stdio.h'). Ce que je ne comprends pas, c'est pourquoi cela a fonctionné dans RedHat exactement comme je l'ai maintenant, mais pas dans Ubuntu. Je poste le code. – ubiquibacon

+2

@typoknig: Si vous avez fait une erreur, par exemple en utilisant 'strlen' sans fournir un prototype approprié, le compilateur peut ne pas avoir l'obligation de vous avertir. Si vous invoquez un comportement indéfini, la norme permet à n'importe quoi de se produire, y compris ce que vous attendez réellement. Il est rarement utile d'analyser pourquoi un programme défectueux a fonctionné sur un système particulier. –

0
gcc -Wall typoknig.c 
typoknig.c:19: error: conflicting types for ‘getline’ 
//usr/include/stdio.h:671: note: previous declaration of ‘getline’ was here 
typoknig.c:21: error: conflicting types for ‘getline’ 
//usr/include/stdio.h:671: note: previous declaration of ‘getline’ was here 

Deux déclarations distinctes de getline qui Andy avait recommandé que vous utilisez my_getline() puisque le premier est déjà partie de stdio.h.

typoknig.c: En fonction 'getline':
typoknig.c: 27: avertissement: déclaration implicite de la fonction 'exit'
typoknig.c: 27: avertissement: déclaration implicite de la intégrée fonction 'exit'

Ce ne peut pas être bon, man exit dit tout en haut:

#include <stdlib.h> 
void exit(int status); 

dont vous avez besoin peut-être d'inclure stdlib.h? Que suppose gcc est la signature d'une fonction non déclarée?

typoknig.c: En fonction 'handle_SIGINT':
typoknig.c: 59: avertissement: déclaration implicite de la fonction 'strlen'
typoknig.c: 59: avertissement: déclaration implicite de la intégrée fonction 'strlen'

Aïe, man strlen à la rescousse:

#include <string.h> 

Heureusement, string.h va aider le prochain et nous avons déjà cloués exit:

typoknig.c: En fonction 'principale':
typoknig.c: 70: avertissement: déclaration implicite de la fonction 'strcpy'
typoknig .c: 70: avertissement: déclaration implicite de la fonction « strcpy » intégrée
typoknig.c: 85: avertissement: déclaration implicite de la fonction intégrée « sortie »

est-ce pas avant processeur astucieux?

typoknig.c:87: warning: implicit declaration of function ‘waitpid’ 
typoknig.c:64: warning: unused variable ‘ret’ 

sayeth man waitpid:

#include <sys/types.h> 
#include <sys/wait.h> 

Ligne 64 est laissé comme un exercice pour le lecteur.

+0

Qu'il compilé du tout sous n'importe quel gcc est le vrai casse-tête. – msw

+0

regardez j'apprécie votre aide, mais peut-être vous avez manqué le "parler clairement" partie de ma question. Je comprends ce que vous dites dans certaines parties de votre réponse, mais pas toutes. Je reçois la plaisanterie de ce que David et vous dites (que je savais déjà) que j'ai des fonctions déclarées deux fois. Il ne semble pas qu'il y ait une telle différence entre les deux systèmes sur lesquels je travaille, et j'ai du mal à comprendre pourquoi cela fonctionne sans erreur dans RedHat mais avec beaucoup d'erreurs dans Ubuntu. Ceci est juste un projet secondaire, donc je ne suis pas profondément préoccupé par cela, j'étais juste curieux de savoir le "pourquoi". – ubiquibacon

0

Getline() ne fait pas partie de la norme C. C'est une extension GNU. En C++ Getline() est standard.

Donc, en ajoutant à votre code devant vos #includes

#define _GNU_SOURCE 

devrait fixer l'avertissement. Voir aussi "man getline" sur linux.