C 关于简单linux shell实现的帮助

C 关于简单linux shell实现的帮助,c,linux,shell,C,Linux,Shell,我正在用c实现一个简单的linux shell版本 我已经成功地编写了解析器,但是在派生子进程时遇到了一些问题。然而,我认为这个问题是由于数组、指针等原因造成的,因为这个项目刚开始使用C语言,对它们还不是很熟悉 我遇到了一个分割错误,不知道是从哪里来的。非常感谢您的帮助 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include &l

我正在用c实现一个简单的linux shell版本

我已经成功地编写了解析器,但是在派生子进程时遇到了一些问题。然而,我认为这个问题是由于数组、指针等原因造成的,因为这个项目刚开始使用C语言,对它们还不是很熟悉

我遇到了一个分割错误,不知道是从哪里来的。非常感谢您的帮助

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>

#define MAX_COMMAND_LENGTH 250
#define MAX_ARG_LENGTH 250

typedef enum {false, true} bool;

typedef struct {
    char **arg;     
    char *infile;   
    char *outfile;  
    int background; 
} Command_Info;

int parse_cmd(char *cmd_line, Command_Info *cmd_info)
{
    char *arg;
    char *args[MAX_ARG_LENGTH]; 

    int i = 0;
    arg = strtok(cmd_line, " ");
    while (arg != NULL) {
        args[i] = arg;
        arg = strtok(NULL, " ");
        i++;
    }

    int num_elems = i;
    if (num_elems == 0)
        return -1;

    cmd_info->infile = NULL;
    cmd_info->outfile = NULL;
    cmd_info->background = 0;

    int iarg = 0;
    for (i = 0; i < num_elems-1; i++)
    {                   
        if (!strcmp(args[i], "<"))
        {
            if (args[i+1] != NULL)
                cmd_info->infile = args[++i];
            else
                return -1;                      
        }

        else if (!strcmp(args[i], ">"))
        {
            if (args[i+1] != NULL)
                cmd_info->outfile = args[++i];
            else 
                return -1;                          
        }

        else
            cmd_info->arg[iarg++] = args[i];
    }

    if (!strcmp(args[i], "&"))
        cmd_info->background = true;
    else
        cmd_info->arg[iarg++] = args[i];

    cmd_info->arg[iarg] = NULL; 

    return 0;   
}


void print_cmd(Command_Info *cmd_info)
{
    int i;  
    for (i = 0; cmd_info->arg[i] != NULL; i++)
        printf("arg[%d]=\"%s\"\n", i, cmd_info->arg[i]);
    printf("arg[%d]=\"%s\"\n", i, cmd_info->arg[i]);    
    printf("infile=\"%s\"\n", cmd_info->infile);
    printf("outfile=\"%s\"\n", cmd_info->outfile);
    printf("background=\"%d\"\n", cmd_info->background);
}

void get_cmd(char* str)
{
    fgets(str, MAX_COMMAND_LENGTH, stdin);
    str[strlen(str)-1] = '\0'; //apaga o '\n' do fim
}

pid_t exec_simple(Command_Info *cmd_info)

{
    pid_t pid = fork();


    if (pid < 0)
    {
        perror("Fork Error");
        return -1;
    }



    if (pid == 0)

    {
        execvp(cmd_info->arg[0], cmd_info->arg);

        perror(cmd_info->arg[0]);
        exit(1);
    }


    return pid;

}

int main(int argc, char* argv[])
{

    while (true)
    {
        char cmd_line[MAX_COMMAND_LENGTH];
        Command_Info cmd_info;

        printf(">>> ");

        get_cmd(cmd_line);

        if ( (parse_cmd(cmd_line, &cmd_info) == -1) )   
            return -1;

        parse_cmd(cmd_line, &cmd_info);



        if (!strcmp(cmd_info.arg[0], "exit"))
            exit(0);

        pid_t pid = exec_simple(&cmd_info);

        waitpid(pid, NULL, 0);  
    }

    return 0;
} 
谢谢。

问题在于cmd_info->arg,它被声明为char**arg,您从未为它分配内存

因此,当您尝试访问它以保存参数时,如cmd_info->arg[iarg++]=args[i],您正在取消对未初始化指针的引用,从而导致分段错误

解决方案是更改命令\u Info结构以如下方式声明arg:

char *arg[MAX_ARG_LENGTH];
问题在于cmd_info->arg,它被声明为char**arg,您从未为它分配内存

因此,当您尝试访问它以保存参数时,如cmd_info->arg[iarg++]=args[i],您正在取消对未初始化指针的引用,从而导致分段错误

解决方案是更改命令\u Info结构以如下方式声明arg:

char *arg[MAX_ARG_LENGTH];

你可以用gdb运行你的程序,当它出现故障时,你可以输入bt来获取堆栈的回溯。这将帮助您准确识别崩溃的位置。str[strlenstr-1]='\0';是不安全的,如果str=;事实上,这对gdb来说是一个完美的任务。。。而且,更重要的是,这是熟悉gdb的完美任务。能够使用GDB来跟踪Sebug位置将是最重要的调试技巧之一,特别是对于新的C开发人员来说。也请考虑默认情况下使用StrutoKyr,如果在线程中处理命令,它将为您节省很多头痛。strtok只需额外花费一个指针就可以将正在进行的工作保存在线程本地存储中。您可以使用gdb运行程序,当程序出现故障时,您可以键入bt以获取堆栈的回溯跟踪。这将帮助您准确识别崩溃的位置。str[strlenstr-1]='\0';是不安全的,如果str=;事实上,这对gdb来说是一个完美的任务。。。而且,更重要的是,这是熟悉gdb的完美任务。能够使用GDB来跟踪Sebug位置将是最重要的调试技巧之一,特别是对于新的C开发人员来说。也请考虑默认情况下使用StrutoKyr,如果在线程中处理命令,它将为您节省很多头痛。strtok只需额外花费一个指针就可以将其正在进行的工作保存在线程本地存储中。