0

コマンド ライン シェルの履歴機能を実装しています。循環配列を実装して、最新の 10 個のコマンドを保持します。また、各コマンドには、合計コマンドがどれであるかを示す整数が付けられます。たとえば、合計 30 個のコマンドが入力された場合、円形配列内の 10 個のコマンドに番号が付けられます (30、29、28、27、...、21)。

ユーザーがコマンド「r」の後に 10 個の命令のうちの 1 つにラベルを付ける番号を挿入した場合、その命令は実行されるはずです。2 ワードのコマンドが正しく受け入れられることを確認しようとすると、セグ フォールトが発生し続けます。誰でも問題が何であるかを指摘できますか。

int main(void)
{
    char inputBuffer[MAX_LINE]; /* buffer to hold the command entered */
    int background;             /* equals 1 if a command is followed by '&' */
    char *args[MAX_LINE/2+1];/* command line (of 80) has max of 40 arguments */

    int position, count, rnum = 0;
    char historyArray[10][MAX_LINE];
    char *holder[MAX_LINE]={0};

    while (1){            /* Program terminates normally inside setup */
        background = 0;
        printf("COMMAND->");
        fflush(0);

        setup(inputBuffer, args, &background);       /* get next command */

        position = (count % MOD_VAL);
        strcpy(historyArray[position],args[0]);

        if(!strcmp("rr",args[0]))
        {
            strcpy(historyArray[position],historyArray[((position-1)+MOD_VAL)%MOD_VAL]);
            printf("%i",count);
            printf("%c",'.');
            printf("%c",' ');
            printf("%s",historyArray[position]);
            printf("%c",'\n');
            strcpy(args[0],historyArray[position]);
        }

        else if(!strcmp("r",args[0])) //SEG FAULT OCCURING IN THIS ELSE-IF BLOCK!
        {
            //args[1] will hold given number
            printf("%c",'\n');
            printf("%s",args[0]);
            printf("%s",args[1]);
            printf("%s",args[2]);
            printf("%c",'\n'); //PRINT STATEMENTS FOR DEBUGGING

            strncpy(holder[0], args[2], MAX_LINE - 1); //SEG FAULT

            rnum = atoi(args[1]);
            strcpy(historyArray[position],historyArray[((position-(count-rnum))+MOD_VAL)%MOD_VAL]);
            strcpy(args[0],historyArray[position]); //CHANGES VALUES OF args[1], args[2]

            if(holder[0] != NULL)
            {
                strncpy(args[1],holder[0],MAX_LINE-1);
                args[2] = NULL;
            }
            else
            {
                args[1] = NULL;
            }

            printf("%c",'\n');
            printf("%s",args[0]);
            printf("%s",args[1]);
            printf("%s",args[2]);
            printf("%c",'\n');
        }

        else if(!(strcmp("h",args[0]))||!(strcmp("history",args[0])))
        {
            int counter = 0;
            while(counter < 10)
            {
                printf("%i",(count - counter));
                printf("%c",'.');
                printf("%c",' ');
                printf("%s", historyArray[((position - counter + MOD_VAL)%MOD_VAL)]);
                printf("%c",' ');
                printf("%c",'\n');
                counter ++;

                if(counter > count)
                    break;
            }
        }
        count++;

        pid_t pid1; //Initialize pid_t variable to hold process identifier
        pid1 = fork(); //Fork process and assign process identifier to "pid1"

        if (pid1 == 0) //Child process
        {
            //Child process executes the command specified by the user and
            //then quits.
            execvp(args[0], args);
            exit(0);
        }
        else //Parent process
        {
            if (background != 1)//Check for inclusion of '&' in command 
            {
                wait(NULL); //Wait for child process to finish executing
            }
        } 

        /* the steps are:
         (1) fork a child process using fork()
         (2) the child process will invoke execvp()
         (3) if background == 0, the parent will wait, 
         otherwise returns to the setup() function. */
    }
}

どんな支援も大歓迎です!

-マット

4

3 に答える 3

3

ここで、argsは文字ポインタの配列です。

しかしstrcpy、2つの引数が必要です-それはまたはである必要がありarrayますcharacter pointer to which memory allocated by malloc

しかし、あなた strcpy(historyArray[position],args[0]);は1つの議論を取りますが、character pointerそれは受け入れられません。

したがって、またはを変更するargs[]と、が削除されます。args[][]args[0] = malloc(some_no)segfault

于 2013-03-08T04:07:02.310 に答える
0

回線でクラッシュが発生していることに注意してください。

else if(!strcmp("r",args[0]))

私があなたなら、コア ファイルをデバッガにロードし、args[0]に渡されたときの の値を確認しstrcmp()ます。

charとの間の型の不一致に関するコンパイラの警告があると思いますchar*。args を として宣言しchar*ます。つまりargs[0]charではなくchar*です。単一の文字を比較するには、代わりに文字を使用しますstrcmp()

else if ('r' != args[0])

C の文字列処理の落とし穴に関する注意事項:

  • strcmp()引数が正しく NUL で終了していない場合、配列の境界に関して安全ではありません
    • strncmp()比較する文字数を制限するために使用します
  • 配列の境界を保護しますがstrncpy()、宛先文字列を NUL で終了することを保証するものではありません
  • strcpy()配列の境界を考慮しません。コピー先の配列が、コピーされる文字列を受け取るのに十分な大きさであることを確認するのはあなたの責任です
于 2013-03-08T03:46:50.210 に答える
-1

およびcharに保持されているポインタが割り当てられたメモリにありません。argsholder

そのため、関数ファミリーを介してそれらを 0 で終わる文字配列 (「文字列」) へのポインターとして参照すると、関数が有効なメモリを指していないポインターを逆参照しようとするためstr*()、未定義の動作につながります。str*()

于 2013-03-08T07:04:11.880 に答える