具有多个命令的C外壳,分段错误(内核转储)

具有多个命令的C外壳,分段错误(内核转储),c,shell,C,Shell,我正试图用C语言为ubuntu编写一个基本的shell。我想在一行中执行几个命令,用分号分隔。我正在尝试运行它,但我得到消息“分段错误(核心转储)” #包括 #包括 #包括 #包括 #包括 #ifdef_WIN32 #包括 #定义chdir\u chdir #否则 #包括 #恩迪夫 #定义最大长度512 int main(int argc,char*argv[]){ char*cmd; 字符行[最大长度]; 字符*令牌[20]; int i=0; int j=0; int k=0; char*a

我正试图用C语言为ubuntu编写一个基本的shell。我想在一行中执行几个命令,用分号分隔。我正在尝试运行它,但我得到消息“分段错误(核心转储)”

#包括
#包括
#包括
#包括
#包括
#ifdef_WIN32
#包括
#定义chdir\u chdir
#否则
#包括
#恩迪夫
#定义最大长度512
int main(int argc,char*argv[]){
char*cmd;
字符行[最大长度];
字符*令牌[20];
int i=0;
int j=0;
int k=0;
char*args[20];
而(1){
printf(“8334>”);
如果(!fgets(直线,最大长度,标准长度))中断;
while((cmd=strtok(行“;”)!=NULL)
{
printf(“\n”,cmd);
strcpy(令牌[i],cmd);
i+=1;
cmd=NULL;
}

对于(j=0;j,我看到的主要问题是,您没有为将字符串复制到
args[I]
token[I]
预留空间;您为指针数组预留空间,但不为指针指向的内容预留空间:

char *token[20]; // reserves place for 20 pointers
...
strcpy(token[i], cmd);  // token[i] has not been initialized...
克服这一问题最简单的方法可能是写作

token[i] = strdup(cmd); 
请注意,
strdpy
,而不是
strcpy
;请注意,
strdup
会自动为保存副本保留足够的内存,而
strcpy
希望此空间以前已被保留

无论如何,不要忘记在不再使用时释放此内存,也不要忘记对
args
执行此操作


代码中可能还有其他问题;例如,当使用
strtok
时,只有第一个调用会通过split行,而所有连续调用都应该通过
NULL
(请参见doku)。但我认为这是您和调试器可以达到的级别:-)问题的根源在于这一行:

strcpy(token[i], cmd);
这是试图将该字符串复制到
char*token[20]
中的一个条目,但这只是一个指针数组,而不是字符串指针数组

也许你可以使用:

token[i] = strdup( cmd );
当然,代码需要检查(!=NULL)
token[i]
以确保对
strdup()
的调用成功,并在使用特定命令后,将该指针传递到
free()


类似的注意事项也适用于
char*args[20];
usage

您的调试器在这里将非常有用。您不知道如何使用调试器?那么是时候开始学习了。为了便于阅读和理解,1)一致地缩进代码。在每个左大括号“{.unindent”之后缩进,在每个右大括号之前缩进(2)遵循公理:每条语句只有一条语句(至多)每个语句的一个变量声明。考虑关闭括号作为单独的语句。3)变量名应该指示内容或用法(或更好,两者都有)。变量名LIE <代码> L>代码>不给出这样的信息。
将不使用,然后使用签名:
int main(void)
为了便于阅读和理解,单独的代码块(for、if、else、while、do…while、switch、case、default)通过一条空行,发布的代码包含一些“神奇”数字。例如,20。“神奇”数字是没有基础的数字。建议使用
#define
enum
语句为这些神奇数字指定有意义的名称,然后在整个代码中使用这些有意义的名称。
token[i] = strdup( cmd );