分段错误 - 将命令拆分为令牌

时间:2016-11-07 19:24:41

标签: c shell segmentation-fault pipe tokenize

我正在实现的代码,我首先用管道然后用空格分割命令。

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指向分配的内存。任何帮助表示赞赏。

编辑:用valgrind检查。结果如下:

==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  

2 个答案:

答案 0 :(得分:0)

这是一个逐个数组索引。

你的while循环结束时commands[i+1]为空。然后将其传递给splitter

改为通过commands[i]

答案 1 :(得分:-1)

当strtok()找到一个标记时,它会在标记后立即将字符更改为\ 0,然后返回指向标记的指针。

相关问题