質問

私は自分のシェルを作る方法についてチュートリアルを追いかけていますが、今数日間立ち往生しています。

二つのこと:

  1. このコードがコンパイルされて実行されているとき、それはランダムにセグメンテーションの障害を持ち、なぜなぜ把握することはできません。
  2. if文 `IF(Ferror!= 0)`常に真実のようです。 main()関数で fgets()が失敗している理由がわからないので奇数です。
  3. これらのトピックに関する情報(またはこのシェルの作成に関するその他のトピック)の情報は大幅に感謝されます。

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

    ここにいくつかの出力があります:

    **[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
    
    .

役に立ちましたか?

解決

ferrorエラーの場合は、ferror(stdin)ではなくferrorをテストする必要があります。後者は関数アドレスです。これはゼロになることはありません。

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

少なくともいくつかのSEGFAULTSの場合、これはあなたが思うことをしません:

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

これはあなたにを伝えます。ポインタの格納方法は、4または8で、 not 引数の数。

だから4つの引数(または8つの)引数がある場合は、が機能するように見えます。もっと持っているならば、それはいくつかの引数を無視しているようです。そしてそれが少ない場合は、void上で欠けている引数を取得し、(ほとんど確実な)セグメンテーション障害を引き起こします。

lengthを独立して計算し、それを渡したり、argsに渡したり、ターミネーターを渡したり、最後に有効な引数を追加します。

        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++;
    }
}
.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top