我试图制作一个贝壳"波什>"它接收Unix命令并不断收到错误的地址错误。我知道我的代码读入命令并解析它们但由于某种原因,我无法让它们执行,相反,我得到了一个错误的地址"错误。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <string.h>
#include <sys/wait.h>
#define MAX_LINE 128
#define MAX_ARGS 10
int main(){
pid_t pid;
char command[MAX_LINE]; /*command line buffer*/
char *commandArgs[MAX_ARGS]; /*command line arg*/
int i;
char *sPtr=strtok(command," ");
int n=0;
printf("bosh>");
fgets(command, MAX_LINE-1,stdin);
command[strlen(command)-1]='\0';
while(strcmp(command,"quit")!=0)
{
n=0;
sPtr=strtok(command," ");
while(sPtr&&n<MAX_ARGS)
{
sPtr=strtok(NULL," ");
n++;
}
commandArgs[0]=malloc(strlen(command)+1);
strcpy(commandArgs[0],command);
if(fork()==0)
{
execvp(commandArgs[0],commandArgs);
perror("execvp failed");
exit(2);
}
pid=wait(NULL);
printf("%s",">" );
fgets(command, MAX_LINE-1,stdin);
command[strlen(command)-1]='\0';
}
printf("Command (%d) done\n", pid);
return 0;
}
答案 0 :(得分:3)
这两行是罪魁祸首:
commandArgs[0]=malloc(strlen(command)+1);
strcpy(commandArgs[0],command);
首先,malloc(strlen(...))
后跟strcpy
是POSIX函数strdup
已经执行的操作。但是,你甚至不需要复制字符串 - 只需将指向原始字符串的指针存储到commandArgs[0]
中即可:
commandArgs[0] = command;
但是,execvp
该命令将采用多少个参数?如果您仔细阅读手册,他们会说:
execv()
,execvp()
和execvpe()
函数提供了一个指向以null结尾的字符串的指针数组,这些字符串表示新程序可用的参数列表。按照惯例,第一个参数应指向与正在执行的文件关联的文件名。 指针数组必须以空指针终止。
您的参数数组不以NULL结尾。要修复它,请使用
commandArgs[0] = command;
commandArgs[1] = NULL; // !!!!
(然后您注意到您实际上想要在 strtok
解析循环中分配参数,以便您可以实际分配所有参数进入commandArgs
数组;并在启用所有警告的情况下编译并解决这些问题,等等。)
答案 1 :(得分:1)
您在其声明中初始化sPtr
,您不需要这样做,因为您从不使用初始值。但初始化会产生未定义的行为,因为它取决于command
数组的内容,此时该数组是不确定的。
作为execvp()
的第二个参数传递的数组应该在最后一个参数后包含一个NULL指针。你不能确保你的确如此。
您还可能因为未能将令牌分配给commandArgs[]
而将所有参数都删除到输入命令。标记化后,您复制第一个标记(仅限)并将副本分配给commandArgs
的第一个元素,但忽略任何其他标记。