0
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define BUF 1024        //I assume that the maximum number of arguments is 1024

main()
{
    char c;
    char *temp;
    char *arg[BUF];                 //the commands
    int i=1,j,k,iter=0;

    while(1)
    {
            i=1;
            iter=0;
            printf("CS21> ");
            temp = malloc(sizeof(char));
            while((c=fgetc(stdin))!='\n')
            {
                    temp = realloc(temp, i*sizeof(char));

                    temp[i-1]=c;
                    i++;
            }

            j=0;
            while(j<strlen(temp))
            {
                    if(temp[j]==' ')
                    {
                            j++;
                            continue;
                    }

                    if(temp[j]!=' ')  //Line 38: Same check performed as Line 42
                    {
                                    k=j;
                                    arg[iter] = malloc(sizeof(char));
                                    while(temp[k]!=' ')    //Line 42: Segmentation Fault here
                                    {
                                            arg[iter] = realloc(arg[iter],(k-j+1)*sizeof(char));
                                            arg[iter][k-j]=temp[k];
                                            k++;
                                    }
                                    iter++;
                                    k++;
                                    j=k;
                                    continue;
                    }
            }
    }
}

こんにちは、上記は私のカスタム シェル コードのサンプル コードです。プログラムが無限に続くことを疑問に思っている場合に備えて、私はまだコードを完成させていません。現在、ある行でセグメンテーション違反が発生しています (コメント済み) が、その理由がわかりません。38 行目で 42 行目と同じチェックを実行しましたが、セグメンテーション違反は発生しませんでした。誰でも私を助けることができますか?

上記の変数のいくつかの目的は次のとおりです。「temp」は、シェルに与えられたコマンド全体を保持するメモリ位置へのポインタです。「args」はポインタの配列で、各ポインタはコマンドの個々の引数を含むメモリ位置を指しています。

たとえば、"temp" は文字列 - gcc hello.c -o hello を保持します。これがシェルに渡された場合です。また、args[0] は「gcc」を指し、args[1] は「hello.c」などを指します。

それが、このコード サンプルの目的です。「temp」から空白を削除した後、すべての引数を「args」に格納します。while(1) ループは、ユーザーがシェルから exit コマンドを呼び出すと終了します。ただし、その部分は個別に行われます。このコードのサンプルを手伝ってくれる人はいますか?

ありがとう!

4

4 に答える 4

1

文字列にスペースがない場合 (最後の引数の場合)、終了しない while(temp[k]!=' ') にループがあります。k > strlen(temp) の場合、ループを停止する必要があります。

私のコメント: バイトごとに読み取り、各文字の後に再割り当てするように教えているのは一体誰ですか? これは厄介です...

于 2013-03-03T11:08:53.663 に答える
0

次の行だと思います:

arg[iter] = malloc(sizeof(char));

がBUF より大きいk場合、値を損傷する可能性があります。また、負の場合itemの値を損なう可能性があります。これは、とがやや近いスタックに格納されており、そのサイズを超える要素を書き込むと、近くに格納されている変数が実際に上書きされる可能性があるためです。tempiterktempargarg

上記の行の前後を印刷kしてみて、それらの値が壊れているかどうかを確認してください。temp

于 2013-03-03T11:06:23.743 に答える
0

ラインで

while((c=fgetc(stdin))!='\n')
{
        temp = realloc(temp, i*sizeof(char));

        temp[i-1]=c;
        i++;
}

一時文字列をヌル終了文字で終わらせないでください

その後、その配列の範囲外に出ます

 while(temp[k]!=' ')    //Line 42: Segmentation Fault here




行を変更する

 temp[i-1]=c; to  temp[i-1]='\n';

while(temp[k]!=' ') to while(temp[k]!='\0')
于 2013-03-03T11:07:23.430 に答える
0

文字列の終わりを示すtemp特別な文字のために、追加の 1 文字スペースを割り当てる必要があります。'\0'

while((c=fgetc(stdin))!='\n')
{
    temp = realloc(temp, i*sizeof(char) + 1);  //1 more char space for '\0'
    temp[i-1]=c;
    i++;
 }
 temp[i] = '\0';  //Indicates the end of String

arg文字列も終了する必要があるわけではありません'\0'

これにより、発生しているセグメンテーション違反を防ぐことができますが、プログラムが失敗する可能性がある別のケースを確認することをお勧めします..

詳細については、こちらを参照してください。

于 2013-03-03T11:20:18.523 に答える