Domanda

Ho seguito un tutorial su come fare il mio shell ma sono stato bloccato per un paio di giorni.

Due cose:

    .
  1. Quando questo codice è compilato e correva, avrà casualmente i guasti di segmentazione e non riesco a capire perché.
  2. L'istruzione if `If (Ferror!= 0)` Sembra sempre vero.Che è strano perché non capisco perché Fets () è in errore nella funzione Main () .
  3. Qualsiasi informazione su questi argomenti (o altri argomenti sulla creazione di questo shell) sarebbe molto apprezzata.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    
    #define MAXSIZE 512
    
    int parseCmd(char *cmd, char *args[])
    {
        printf("LOGGER: parseCmd(cmd=%s, args=%p)\n", cmd, args);
    
        char cmdDelims[] = {' ','>'};
    
        char *cmdReader;
        cmdReader = strtok(cmd, cmdDelims);
    
        int i = 0;
        while (cmdReader != NULL)
        {       
            args[i] = strdup(cmdReader);
    
            printf("LOGGER: args[%d]=%s\n", i, args[i]);
    
            cmdReader = strtok(NULL, cmdDelims);
            i++;
        }
        return 0;
    }
    
    void printToLine(char *args[])
    {
        int length;
        length = sizeof(args) / sizeof(char);
    
        int i = 0;
        while (i < length)
        {
            printf("%s\n", args[i]);
            i++;
        }
    }
    
    int main(int argc, char *argv[]) 
    {   
        char *in;
        in = malloc(MAXSIZE);
    
        char *args[15];
        char *cmd = NULL;
    
        int errorBit = 0;
        int terminationBit = 1;
        char error_message[30] = "An error has occurred\n";
    
        char inDelims[] = "\n";
    
        while (terminationBit)
        {
            printf("mysh>");
    
            // get input from command line
            fgets(in, MAXSIZE, stdin);
            if (ferror != 0)
            {
                perror(error_message);
            }
    
            // get pointer to command line input w/o the newline
            cmd = strtok(in, inDelims);
    
            // parse the command into separate arguments
            errorBit = parseCmd(cmd, args);
            if (errorBit)
            {
                perror(error_message);
                exit(1);
            }
    
            printToLine(args);
    
            // check if the user wants to exit the shell
            if (strcmp(*args, "exit") == 0)
            {
                terminationBit = 0;
            }
        }
        return 0;
    }
    
    .

    Ecco alcune uscite:

    **[ray@12] (6)$ mysh**
    mysh>1 2 3
    An error has occurred
    : Success
    LOGGER: parseCmd(cmd=1 2 3, args=0x7fff4a50b080)
    LOGGER: args[0]=1
    LOGGER: args[1]=2
    LOGGER: args[2]=3
    1
    2
    3
    Segmentation fault (core dumped)
    **[ray@12] (7)$ mysh**
    mysh>1 2 3 4 5 6 7 8 9 10
    An error has occurred
    : Success
    LOGGER: parseCmd(cmd=1 2 3 4 5 6 7 8 9 10, args=0x7fffba053d70)
    LOGGER: args[0]=1
    LOGGER: args[1]=2
    LOGGER: args[2]=3
    LOGGER: args[3]=4
    LOGGER: args[4]=5
    LOGGER: args[5]=6
    LOGGER: args[6]=7
    LOGGER: args[7]=8
    LOGGER: args[8]=9
    LOGGER: args[9]=10
    1
    2
    3
    4
    5
    6
    7
    8
    mysh>1 2 3
    An error has occurred
    : Success
    LOGGER: parseCmd(cmd=1 2 3, args=0x7fffba053d70)
    LOGGER: args[0]=1
    LOGGER: args[1]=2
    LOGGER: args[2]=3
    1
    2
    3
    4
    5
    6
    7
    8
    
    .

È stato utile?

Soluzione

Per l'errore ferror, è necessario testare ferror(stdin), non ferror.Quest'ultimo è l'indirizzo della funzione, che non sarà mai zero:

if (ferror(stdin) != 0)
{
    perror(error_message);
}
.

Per almeno alcuni dei segfault, questo non fa quello che pensi:

length = sizeof(args) / sizeof(char);
.

Questo ti dirà quanti byte vengono utilizzati per memorizzare il puntatore , che è 4 o 8 a seconda, e non il numero di argomenti.

Quindi se si dispone di quattro (o otto) argomenti, lo farà per funzionare.Se ne hai di più, sembrerà ignorare alcuni argomenti.E se hai meno, recupererà gli argomenti mancanti dall'altra parte del vuoto, con conseguente (quasi sicuro) Guasto di segmentazione.

È necessario calcolare length in modo indipendente e passarlo avanti o memorizzare un po 'di terminatore in args, ad esempio aggiungendo un argomento null dopo l'ultimo argomento valido che trovi:

        cmdReader = strtok(NULL, cmdDelims);
        i++;
    }
    args[i] = NULL;
    return 0;
}

void printToLine(char *args[])
{
    int i = 0;
    while (args[i])
    {
        printf("%s\n", args[i]);
        i++;
    }
}
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top