2012-04-22 7 views
0

私は自分のシェルをC言語で書こうとしています。以下のコードはパイプなしのコマンドでは動作しますが、そうでない場合は動作しません。シェルの作成。

--trace-children = yesと--track-origins = yesを使用すると、 "Syscall param execve(argv)が未初期化バイトを指しています"(以下の完全なエラーを参照)。関連する方法では

(以下makeargsを参照)valgrindのは、このライン "のargv =(CHAR *)はmalloc((+ 1カウント)*はsizeof(文字で "初期化されていない値は、ヒープ割り当てによって作成された" 私に言っています*)); "

"ls | sort"のテスト入力を使用すると、valgrindは "size 12 alloc'dのブロック"と表示します。私はlsとsortがそれぞれmakeargを呼び出すために可能な方法は見当たらず、両方とも8バイトが割り当てられなければなりません。char *には4バイト、execvpにはchar *引数配列の

このコマンドを実行すると、プログラムがハングします。

なぜこれが起こっているのか分からないのは、makeargs(パイプなし)を1回だけ呼び出すと機能するためです。どんな入力も感謝します。

void execCommand(char** commandParts, int pipeCount) 
{ 
    const int PIPE_READ = 0; 
    const int PIPE_WRITE = 1; 
    int numCommands = pipeCount + 1; 
    int newfds[2]; 
    int oldfds[2]; 

    int k = 0; 
    for(k; k < numCommands; k++) 
    { 

    //more commands exist 
    if(k < pipeCount) 
    { 
     if (pipe(newfds) == -1) 
     { 
     perror("new pipe error"); 
     exit(EXIT_FAILURE); 
     } 
    } 

    if(fork() == 0) //child 
    { 
     //is prev command 
     if(k > 0) 
     { 
     dup2(oldfds[PIPE_READ], STDIN_FILENO); 
     close(oldfds[PIPE_READ]); 
     close(oldfds[PIPE_WRITE]); 
     } 

     //more commands exist 
     if(k < pipeCount) 
     { 
     close(newfds[PIPE_READ]); 
     dup2(newfds[PIPE_WRITE], STDOUT_FILENO); 
     close(newfds[PIPE_WRITE]); 
     } 
     char** args = NULL; 
     int argcount = makeargs(commandParts[k], &args); 

     if(execvp(args[0], args) == -1) 
     { 
     printf("%s: command not found \n", args[0]); 
     } 
    } 
    else //parent 
    { 
     int status; 
     waitpid(-1, &status, NULL); 

     //is prev command 
     if(k > 0) 
     { 
     close(oldfds[PIPE_READ]); 
     close(oldfds[PIPE_WRITE]); 
     } 
     //more commands exist 
     if(k < pipeCount) 
     { 
     oldfds[PIPE_READ] = newfds[PIPE_READ]; 
     oldfds[PIPE_WRITE] = newfds[PIPE_WRITE]; 
     } 
    } 
    //there are pipes 
    if(pipeCount > 0 && k > 0) 
    { 
     close(newfds[PIPE_READ]); 
     close(newfds[PIPE_WRITE]); 
    } 
    // if(argcount > 0) 
    // cleanArgs(argcount, args); 
    } 
} 

呼び出さメイク引数方法

int makeargs(char *s, char *** argv) 
{ 
    stripLeadingAndTrailingSpaces(s); 
    int k =0, count = 0; 
    for(k; k < strlen(s); k++) 
    { 
    if(s[k] == ' ') 
    count++; 
    } 
    count++; 

    char* parts = strtok (s," "); 
    strip(parts); 

    *argv = (char **)malloc((count+1) * sizeof(char*)); 

    (*argv)[0] = (char *)malloc(strlen(parts)+1); 
    strcpy((*argv)[0], parts); 

    int i = 1; 
    for(i; i < count; i++) 
    { 
    parts = strtok (NULL, " "); 
    if(parts != NULL) 
    { 
     strip(parts); 
     (*argv)[i] = (char *)malloc(strlen(parts)+1); 
     strcpy((*argv)[i], parts); 
    } 
    } 
    (*argv)[count] = NULL; 

    return count; 
} 

valgrindの出力あなたはそこにいくつかの悪いカウントを持っている

==3603== Syscall param execve(argv) points to uninitialised byte(s) 
==3603== at 0x40E2CDF: execve (execve.c:60) 
==3603== by 0x40E314E: execvp (execvp.c:30) 
==3603== by 0x8049069: main (cscd340_s12_hw2.c:250) 
==3603== Address 0x41c617c is 4 bytes inside a block of size 12 alloc'd 
==3603== at 0x4028876: malloc (vg_replace_malloc.c:236) 
==3603== by 0x8049416: makeargs (ush.c:100) 
==3603== by 0x8048E61: execCommand (cscd340_s12_hw2.c:191) 
==3603== by 0x8049069: main (cscd340_s12_hw2.c:250) 
==3603== Uninitialised value was created by a heap allocation 
==3603== at 0x4028876: malloc (vg_replace_malloc.c:236) 
==3603== by 0x8049416: makeargs (ush.c:100) 
==3603== by 0x8048E61: execCommand (cscd340_s12_hw2.c:191) 
==3603== by 0x8049069: main (cscd340_s12_hw2.c:250) 

答えて

0

最後に、I(s)は私のstripLeadingAndTrailingSpacesに問題を追跡しました。私はどうかを確認するために '/ 0' をチェックして

  1. :私は昔のストリップ方法に問題のカップルがありました

    void stripLeadingAndTrailingSpaces(char temp[]) 
    { 
        int len = strlen(temp), start = 0; 
        while(isspace(temp[len])) 
        { 
         len--; 
        } 
        while(isspace(temp[start])) 
        { 
         start++; 
        } 
        memmove(temp, temp + start, len); 
    } 
    

    があったが、

    void stripLeadingAndTrailingSpaces(char temp[]) 
    { 
        int len = strlen(temp)+1, start = 0; 
        while(isspace(temp[len-2])) 
        { 
         temp[len-2] = '\0'; 
         len--; 
        } 
        while(isspace(temp[start])) 
        { 
         start++; 
         len--; 
        } 
        memmove(temp, temp + start, len); 
    } 
    

    を必要

    それは最後のスペースだった。

  2. 新しい終端に新しいヌルターミネータを適用していませんでした。
  3. 正面からスペースをカットするときの長さを減らしていませんでした。
0

countはスペースの数ではなく、単語の数でありますコマンドライン。これは、コピーコードに影響を与えます。

for(i; i < count; i++) 
{ 
    parts = strtok (NULL, " "); 
    if(parts != NULL) 
    { 
    ... 
    } 
} 

入力コマンド・ラインで、あまりにも少しの単語がある場合は、argvでいくつかの末尾のエントリが初期化されていないだろう。あなたは、おそらくこのような何かをしたい:

for(i; i <= count; i++) 
{ 
    parts = strtok (NULL, " "); 
    if(parts != NULL) 
    { 
    ... // consider using strdup 
    } 
    else 
    { 
    (*argv)[i] = NULL; 
    break; 
    } 
} 
+0

ありがとうございます。あなたの提案された構造はより良いですし、私はスペースを数えた後にカウントを追加すると思ったので、それは問題ではありませんでした。私は問題を考え出した。探してくれてありがとう。 – user1349071

関連する問題