2016-11-07 43 views
0

我正在执行的代码中,我首先通过管道然后通过空格分割命令。分割错误 - 将命令分割为令牌

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有关,其中我传递了每个命令的标记。我不明白为什么会发生这种情况,因为分配内存,并从我的理解,我只是指针指向分配的内存。任何帮助赞赏。

编辑:用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 
+3

你使用过调试器吗?如果您希望我们提供帮助,请提供[mcve]。我们无法调试不完整的代码。例如,什么是'cmd'? – kaylum

+0

可能是未初始化的fd [2]数组。这也可能是一个CMD变量本身的问题,我不知道它是如何初始化的。对于像这样的错误,我喜欢http://valgrind.org/,以防你在Linux上。不过,我同意@kaylum调试器信息真的有助于理解你的问题:) – PlatinTato

+0

@JacobusConradi我将用valgrind测试它并更新我的文章。谢谢。 –

回答

-1

当的strtok()发现令牌,它改变了字符令牌成\ 0后立即,然后返回一个指向该令牌。

+0

found [this](http://www.c-howto.de/tutorial-strings-zeichenketten-stringfunktionen-zerteilen-strtok.html)示例。他使用它几乎完全一样 – PlatinTato

+1

而??对你的回答不太模糊,并且在解释OP与代码的关系时更加明确。 – kaylum

+0

我在通过管道进行标记之前测试了splitter(),然后继续使用代码并正确完成标记,没有出现分段错误,并且当我按照与第二部分完全相同的方法获取此错误时。编辑:分离器代码是100%我没有与上面提到的链接 –

0

这是一个偏移数组索引。

您的while循环完成时commands[i+1]为空。然后你将它传递给splitter

改为通过commands[i]