我在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;
}
感谢。
答案 0 :(得分:4)
问题在于cmd_info->arg
,它被声明为char **arg
,你永远不会为它分配内存。
因此,当您尝试访问它以保存此cmd_info->arg[iarg++] = args[i]
之类的参数时,您将取消引用未初始化的指针,从而导致分段错误。
解决方案是更改Command_Info
结构以声明arg
,如下所示:
char *arg[MAX_ARG_LENGTH];