我正在实现的代码,我首先用管道然后用空格分割命令。
int main(){
pid_t pid;
while (1) {
printf("$ ");
char *cmd;
ssize_t size=0;
getline(&cmd,&size,stdin);
if (cmd[strlen(cmd)-1]== '\n') {cmd[strlen(cmd)-1]='\0';}
char** commands = splitter(cmd,"|");
int i=0;
int fd[2],in=0;
while (commands[i+1]!=NULL){
pipe(fd);
char **args = splitter(commands[i]," \t");
pid = fork();
if (pid==-1) {exit(EXIT_FAILURE);}
else if (pid==0){
close(fd[0]);
changeIO(in,0);
changeIO(fd[1],1);
execvp(args[0],args);
}
else{
waitpid(pid,NULL,0);
close(fd[1]);
close(in);
in = fd[0];
}
i++;
}
char **args = splitter(commands[i+1]," \t");
changeIO(in,0);
execvp(args[0],args);
}
}
以下是上述代码使用的函数的实现
void changeIO(int oldfd,int newfd){
if (oldfd!=newfd){
dup2(oldfd,newfd);
close(oldfd);
}
}
char** splitter(char* stringToSplit, char* delimiter){
char *token;
int initial_size = 300;
char** args = malloc(initial_size*sizeof(char*));
token = strtok(stringToSplit,delimiter);
int index = 0;
while (token != NULL) {
args[index] = token;
index++;
if (index >= initial_size) {
initial_size = initial_size + 100;
args = realloc(args,initial_size*sizeof(char*));
if (!args) exit(EXIT_FAILURE);
}
token = strtok(NULL,delimiter);
}
args[index] = NULL;
return args;
}
确定执行代码我在用户输入中输入命令时出现分段错误。测试各种选项我意识到它与char** args
有关,我在其中传递每个命令的标记。我无法理解为什么会发生这种情况,因为内存已经分配,而且根据我的理解,我只是将指针args指向分配的内存。任何帮助表示赞赏。
==3361== Memcheck, a memory error detector
==3361== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3361== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==3361== Command: ./mysh3
==3361==
==3361== Conditional jump or move depends on uninitialised value(s)
==3361== at 0x40AFE97: getdelim (iogetdelim.c:59)
==3361== by 0x40ACDD1: getline (getline.c:32)
==3361== by 0x80486C4: main (in /home/dimitris/Desktop/mysh3)
==3361==
$ ls
==3361== Invalid read of size 1
==3361== at 0x4101CAA: execvpe (execvpe.c:50)
==3361== by 0x4101B33: execvp (execvp.c:26)
==3361== by 0x804885F: main (in /home/dimitris/Desktop/mysh3)
==3361== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==3361==
==3361==
==3361== Process terminating with default action of signal 11 (SIGSEGV)
==3361== Access not within mapped region at address 0x0
==3361== at 0x4101CAA: execvpe (execvpe.c:50)
==3361== by 0x4101B33: execvp (execvp.c:26)
==3361== by 0x804885F: main (in /home/dimitris/Desktop/mysh3)
==3361== If you believe this happened as a result of a stack
==3361== overflow in your program's main thread (unlikely but
==3361== possible), you can try to increase the size of the
==3361== main thread stack using the --main-stacksize= flag.
==3361== The main thread stack size used in this run was 8388608.
==3361==
==3361== HEAP SUMMARY:
==3361== in use at exit: 2,520 bytes in 3 blocks
==3361== total heap usage: 5 allocs, 2 frees, 4,568 bytes allocated
==3361==
==3361== LEAK SUMMARY:
==3361== definitely lost: 0 bytes in 0 blocks
==3361== indirectly lost: 0 bytes in 0 blocks
==3361== possibly lost: 0 bytes in 0 blocks
==3361== still reachable: 2,520 bytes in 3 blocks
==3361== suppressed: 0 bytes in 0 blocks
==3361== Rerun with --leak-check=full to see details of leaked memory
==3361==
==3361== For counts of detected and suppressed errors, rerun with: -v
==3361== Use --track-origins=yes to see where uninitialised values come from
==3361== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault
答案 0 :(得分:0)
这是一个逐个数组索引。
你的while循环结束时commands[i+1]
为空。然后将其传递给splitter
。
改为通过commands[i]
。
答案 1 :(得分:-1)
当strtok()找到一个标记时,它会在标记后立即将字符更改为\ 0,然后返回指向标记的指针。