Frage

Ich habe ein Tutorial verfolgt, wie man meine eigene Shell erstellt, aber ich stecke jetzt seit ein paar Tagen fest.

Zwei Dinge:

  1. Wenn dieser Code kompiliert und ausgeführt wird, weist er zufällig Segmentierungsfehler auf und ich kann nicht herausfinden, warum.
  2. Die if-Anweisung 'if (ferror != 0)' scheint immer wahr zu sein.was seltsam ist, weil ich nicht verstehe warum fget() versagt in der wichtigsten() Funktion.

Alle Informationen zu diesen Themen (oder anderen Themen zum Erstellen dieser Shell) wären sehr dankbar.

#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;
}

Hier sind einige Ausgaben:

**[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
War es hilfreich?

Lösung

Für die ferror fehler, Sie müssen testen ferror(stdin), nicht ferror.Letzteres ist die Funktionsadresse, die niemals Null sein wird:

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

Zumindest für einige der Segfehler macht dies nicht das, was Sie denken:

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

Das wird dir sagen wie viele Bytes werden zum Speichern des Zeigers verwendet, was 4 oder 8 abhängig ist, und nicht die Anzahl der Argumente.

Wenn Sie also vier (oder acht) Argumente haben, wird es erscheinen arbeiten.Wenn Sie mehr haben, scheint es einige Argumente zu ignorieren.Und wenn Sie weniger haben, werden die fehlenden Argumente aus der Leere abgerufen, was zu einem (fast sicheren) Segmentierungsfehler führt.

Sie müssen berechnen length unabhängig voneinander und geben Sie es weiter oder speichern Sie einen Terminator darin args, zum Beispiel das Hinzufügen eines Nullarguments nach dem letzten gültigen Argument, das Sie finden:

        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++;
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top