繁体   English   中英

使用 strtok() 时 C 编程中的分段错误

[英]Segmentation Fault in C programming when using strtok()

我正在编写一个简单的 shell 并且命令 (ls & whoami;) 有效,但是当我仅键入命令 ls 时,代码由于第 51 行的分段错误而中断。我想知道如何 go 关于这个我使用了 Valgrind 和大量的 printf 语句,但似乎没有任何效果。 让我知道你的想法。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>

#define MAX_LINE 80
#define MAX_CHAR 100

int main()
{
    int should_run = 1;
    char line[MAX_CHAR];
    char *args[MAX_LINE/2 +1];
    int ampersandFlag = 0;


    /*---------------------------------------------------*/
    /*                Start of The Program               */

    while(should_run){
        printf("osh>");
        fgets(line,MAX_CHAR,stdin);

        /* get rid of newline char */
        int k = 0;
        while(line[k] != '\n'){
            k++;
        }
        line[k] = '\0';

        /* get rid of semicolon char */
        int l = 0;
        while(line[l] != ';'){
            l++;
        }
        line[l] = '\0';


        int i = 0;
        args[i] = strtok(line, " ");

        if(args[i] == NULL){
            return 1;
        }

        while(args[i] != NULL){
            printf("%s\n", args[i]);
            i++;
            args[i] = strtok(NULL, " ");
        }

        /* Handles the exit command.  */
        int a = 0;
        if(strcmp(args[a], "exit") == 0){
            exit(0);
        }
        if(strcmp(args[1], "&") == 0){
            args[1] = NULL;
            ampersandFlag = 1;
        }

        /*---------------------------------------------------*/
        /*                     Start Forking                 */

        int returnForkValue = fork();
        int status;

        if(returnForkValue < 0){
            perror("Fork Failed");
        }

        else if(returnForkValue == 0){
            printf("This is the child\n");
            if(ampersandFlag == 1){
                int stat;
                int retFork = fork();

                if(retFork == 0){
                    printf("This is second child");
                    execvp(args[2],args);
                }
                else{
                    printf("This is the second parent");
                    waitpid(retFork, &stat, 0);
                }
            }
            execvp(args[0],args);
            printf("This won't be printed if execvp is successul\n");
        }

        else{
            printf("This is the parent\n");
            waitpid(returnForkValue, &status, 0);
        }
    }
    return 0;
}

如果您只有一个标记,则只有args[0]将指向一个有效的字符串。 下一个args[1]将是NULL指针。 args的所有其他元素都将未初始化。

在这种情况下,行

        if(strcmp(args[1], "&") == 0){

将尝试使用NULL指针作为字符串。

循环之后

while(args[i] != NULL){

变量i将包含令牌的数量。

您应该只使用 index values < i来访问args

执行第二个命令的代码是错误的。 代替

                    execvp(args[2],args);

你必须使用

                    execvp(args[2],&args[2]);

但这仅在令牌数至少为 3 时才有效。

顺便说一句:您的代码有点不一致。 要检查"exit" ,您使用变量a作为args的索引,对于其他比较,您使用硬编码数字。

当我使用valgrind运行程序并输入ls时,我收到一条错误消息,显示NULL指针访问。

==30002== Invalid read of size 1
==30002==    at 0x483EED4: strcmp (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==30002==    by 0x10943A: main (test.c:58)
==30002==  Address 0x0 is not stack'd, malloc'd or (recently) free'd

我收到一条额外的错误消息

==30002== Conditional jump or move depends on uninitialised value(s)
==30002==    at 0x10933C: main (test.c:34)

发生这种情况是因为您的循环

while(line[l] != ';'){

不检查终止NUL ( '\0' ) 字符,如果它不包含分号,它将读取字符串的末尾。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM