使用函数变换char *数组但函数退出后字符串值发生变化 .

我正在构建一个简单的命令行解释器 . 它从stdin读取用户输入并解析它以在单独的子进程中运行程序 .

用户输入的格式为:... arg1到arg4是可能的命令行参数 .

(我约束输入格式,路径长<100个字符,每个cmd行参数<20个字符长,最多有4厘米线参数)

现在main()函数只读入一行用户输入 .

我的问题是,我抽象输入解析并存储到一个名为extractArgs(char **,char *)的函数中 . 此函数解析输入并提取execv(char * argc,char * argv [])参数所需的数据 .

它肯定正确解析输入 . 我将调试print语句放在main和extractArgs中以打印出argv数组中的字符串 . extractArgs中的一个显示argv保存正确的值,但main中的值打印废话 .

我怀疑它与在extractArgs执行完毕后被回收的内存有关,所以当旧的值被覆盖时,argv指针最终指向无意义 .

它是否正确?我能做些什么来阻止它?我必须使用malloc吗?有没有办法简单地保持argv数组中的指针不被回收?

// argv is the char* array to store cmd args from stdin for execv, 
// path is string to store path from user input
int extractArgs(char** argv, char* path)
{
    const char* fmessageNotFound = "%s not found\n";
    struct stat buf;

    const char delim[2] = " ";
    char argStr[90];
    char* token;
    int i;

    scanf("%s", path); // get path

    // handle invalid program path
    if (stat(path, &buf) == -1) 
    {
        printf(fmessageNotFound, path);
        return -1;
    }

    argv[0] = path; // argv[0] must be program name
    argv[1] = NULL; // set terminating element for 0 argument case.

    // read all cmd line args.
    // constraints: up to 4 args, arg lengths <20 chars
    fgets(argStr, 90, stdin);
    argStr[strcspn(argStr, "\n")] = '\0'; // clear trailing \n

    // populate argv array
    token = strtok(argStr, " ");
    for (i = 1; i < 5 && token != NULL; i++)
    {
        argv[i] = token;
        token = strtok(NULL, " ");
    }
    // set terminating element after populating argv
    argv[i] = NULL;

    // test and print all the arguments
    i = 0;
    while (argv[i] != NULL) {

        // EVERYTHING WORKS HERE
        printf("%s\n", argv[i]);
        i++;
    }

    return 0;
}

int main()
{
    pid_t chpid;
    char* argv[6];  // max 4 cmd args + name + NULL terminator
    char path[100]; // command path length <100

    if (extractArgs(argv, path) == -1) // invalid path
    {
        fgets(path, 100, stdin); // clean up newline
        return;
    }

    // Print values in argv
    int i = 0;
    while (argv[i] != NULL) {

        // PRINTS NONSENSE.
        printf("%s\n", argv[i]);
        i++;
    }

    chpid = fork();
    if (chpid == 0)
    {
        execv(path, argv);
    }
    wait(NULL);
    return 0;
}

回答(1)

2 years ago

extractArgs 函数中,存储指向 argv 数组中的本地数组 argStr 的指针 .

一旦函数返回,那些指针就不再有效,因为 argStr 已超出范围 . 当您尝试使用 argv 数组中的杂散指针时,这会导致未定义的行为 .