【问题标题】:Unexpected behavior with my token function我的令牌功能出现意外行为
【发布时间】:2021-02-04 04:26:02
【问题描述】:

我正在尝试用 C 语言编写一个简单的 Shell。最终,我将实现进程和管道等的分叉。但是,现在,我只是想弄清楚所有的逻辑。

我有一个部分工作的 shell:当我键入 exit 时,它退出了......但是,我的令牌函数似乎无法正常工作。

我在这里做错了什么?我不确定它为什么会出现段错误。

Tokenwhile 循环中打印一次,然后出现段错误并崩溃。

#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define MAX_BUF_SZ 1024

void checkForPipe(char *string, bool *pipe_bool);
void checkForRedirect(char *string, bool *redirect_bool);
void tokenizeInput(char *string, bool pipe, bool redirect);
int main()
{
    char *ptr;
    bool is_pipe = 0;
    bool is_redirect_out = 0;
    bool is_exit = 0;

    ptr = (char*)malloc(MAX_BUF_SZ);

    while(!is_exit)
    {
        // Diplay prompt
        char cur_dir[MAX_BUF_SZ];
        getcwd(cur_dir, MAX_BUF_SZ);
        printf("SHELL:%s$ ", cur_dir);

        fgets(ptr, MAX_BUF_SZ, stdin);
        checkForPipe(ptr, &is_pipe);
        checkForRedirect(ptr, &is_redirect_out);
        printf("pipe flag = %d\n", is_pipe);
        printf("redirect flag = %d\n", is_redirect_out);
        if(strcmp(ptr, "exit\n") == 0)
        {
            is_exit = 1;
        }

        tokenizeInput(ptr, is_pipe, is_redirect_out);

    }

    return 0;

}

void checkForPipe(char *string, bool *pipe_bool)
{
    char *check_for_pipes;
    char *clean_compare;
    check_for_pipes = (char*)malloc(MAX_BUF_SZ);
    clean_compare = (char*)malloc(MAX_BUF_SZ);

    strcpy(check_for_pipes, string);
    strcpy(clean_compare, string);

    char * token = strtok(check_for_pipes, "|");

    if(strcmp(token, clean_compare) == 0)
        {
         free(clean_compare);
         free(check_for_pipes);
        }

    else
    {
        *pipe_bool = 1;
        free(clean_compare);
        free(check_for_pipes);
    }
}

void checkForRedirect(char *string, bool *redirect_bool)
{
    char *check_for_redirects;
    char *clean_compare;
    check_for_redirects = (char*)malloc(MAX_BUF_SZ);
    clean_compare = (char*)malloc(MAX_BUF_SZ);

    strcpy(check_for_redirects, string);
    strcpy(clean_compare, string);

    char * token = strtok(check_for_redirects, ">");

    if(strcmp(token, clean_compare) == 0)
        {
         free(clean_compare);
         free(check_for_redirects);
        }

    else
    {
        *redirect_bool = 1;
        free(clean_compare);
        free(check_for_redirects);
    }

}

void tokenizeInput(char *string, bool pipe, bool redirect)
{
    char *copy_string;
    copy_string = (char*)malloc(MAX_BUF_SZ);

    strcpy(copy_string, string);

    if(pipe == 0 && redirect == 0)
    {
        char  **args = {NULL};
        char *token = strtok(copy_string, " ");
        int i = 0;
        printf("%s\n", token);
        while(token != NULL)
        {
            args[i] = token;
            strtok(NULL, " ");
            printf("%s\n", token);
            i++;
        }
    }
    /* printf("%s\n%s\n%s\n", args[0], args[1], args[2]); */
}

【问题讨论】:

  • 使用调试器。至少您应该获得触发段错误的确切代码行并将其发布在您的问题中。您还可以使用调试器检查状态以查找可疑值和行为。
  • char **args = {NULL}; 这行不通。它不是一个适当大小的数组。您需要一个至少足够大的数组来存储所有令牌。
  • char **args 是一个 指向指向 char 的指针的单个指针 -- 它只是一个指向包含更多指针的内存块或 NULL 的指针(不是它们的数组)。与任何指针一样,您必须确保它指向已分配给指针的有效内存。 (此时没有——这意味着它只是指向 NULL 的指针。)args[i] 取消引用 NULL 指针,所以 BAM !段错误!

标签: c linux shell strtok


【解决方案1】:

问题出在args[i] 我修改了你的代码如下:

假设您有一个预先知道的令牌数量,即MAX_BUF_SZ。 您分配char* 类型的MAX_BUF_SZ 指针

 char **args = malloc(MAX_BUF_SZ * sizeof(char *));

在循环中,你仍然需要在使用它之前分配每个指针char*

while(token != NULL)
 {
            args[i] = (char *)malloc(strlen(token)+1);
            printf("%s\n", token);
            args[i] = token;
            token = strtok(NULL, " ");
            i++;
  }

整个函数是这样的:

void tokenizeInput(char *string, bool pipe, bool redirect)
{

    char *copy_string;
    copy_string = (char*)malloc(MAX_BUF_SZ);

    strcpy(copy_string, string);
    // suppose we would have MAX_BUF_SZ tokens
    char **args = malloc(MAX_BUF_SZ * sizeof(char *));
    if(pipe == 0 && redirect == 0)
    {
        char *token = strtok(copy_string, " ");
        int i = 0;
        //printf("token %s\n", token);

        while(token != NULL)
        {
            args[i] = (char *)malloc(strlen(token)+1);
            printf("%s\n", token);
            args[i] = token;
            token = strtok(NULL, " ");
            i++;
        }
    }
    /* printf("%s\n%s\n%s\n", args[0], args[1], args[2]); */
}

这是我正在运行的示例:

SHELL:D:\Users\T0180694\Documents\Mes Outils Personnels\PAN\PAN_folder$ test is essai of you and me
pipe flag = 0
redirect flag = 0
test
is
essai
of
you
and
me

【讨论】:

  • 这是一大堆指针——但至少它们是有效的指针:)
猜你喜欢
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-01
  • 1970-01-01
  • 2019-03-29
相关资源
最近更新 更多