无法在C中创建shell(Seg-Fault和ferror)

时间:2012-10-03 20:22:14

标签: c segmentation-fault fgets ferror

我一直在关注如何制作自己的shell的教程,但我已经被困了几天了。

两件事:

  1. 编译并运行此代码时,它将随机出现分段错误,我无法弄清楚原因。
  2. if语句`if(ferror!= 0)`似乎总是如此。这很奇怪,因为我不明白为什么 fgets() main()函数中失败。
  3. 有关这些主题的任何信息(或有关创建此shell的其他主题)将不胜感激。

    #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
    

1 个答案:

答案 0 :(得分:3)

对于ferror错误,您需要测试ferror(stdin),而不是ferror。后者是函数地址,永远不会为零:

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

对于至少一些段错误,这不符合您的想法:

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

这将告诉你用于存储指针的字节数,取决于4或8,参数的数量。

因此,如果您有四个(或八个)参数,它将显示。如果你有更多,它似乎会忽略一些参数。如果你的数量较少,它将从Void中获取缺少的参数,从而导致(几乎可以肯定的)分段错误。

您需要独立计算length并将其传递,或在args中存储一些终结符,例如在您找到的最后一个有效参数后添加NULL参数:

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