strtok() 覆盖它的源字符串

strtok() overwrites its source string

我正在写一个玩具bashshell。我现在的目标是在环境中循环寻找可以找到特定命令的路径。现在我正在用“:”分隔路径(例如“/home/user/bin:home/user/.local/bin:/usr/local/sbin”等),对于给我的每条路径,将该路径复制到新字符串 finalPath,然后将“/cmd”连接到末尾。

我的问题是,当我尝试将路径的内容复制到 finalPath 时,我对 finalPath 所做的任何更改都会反映到路径中。由于代码是正确的,path 只会被设置为 "home/user/bin" 一次,循环并再次设置为相同的东西,然后分词器命中 "NULL" 并终止 while 循环。

这表明 pathfinalPath 正在共享一个内存地址,但是由于 strcpy 理论上在内存中创建了一个新副本,所以我的字符串和指针一定有问题。

知道是什么导致了这种意外行为吗?

编辑:当我注释掉 strcpy

时,这段代码按预期执行

我的代码的精简版如下:

int findpath(char* cmd, command_t* p_cmd) {
    char* path_var;

    path_var = getenv( "PATH" );

    char* path;
    char tempEnv[sizeof(path_var)];
    strcpy(tempEnv, path_var);
    path = strtok(tempEnv, ":");

    while(path != NULL) {
        char fullPath[1000];
        strcpy(finalPath, path);
        printf("path: %s\n", path);
        printf("finalPath: %s\n", finalPath);
        path = strtok(NULL, ":");
    }

BLUEPIXY 是正确的:tempEnv 对您的字符串来说不够大。尝试:

char *tempEnv;
tempEnv = malloc(strlen(path_var)+1);
strcpy(tempEnv, path_var);

最后

free(tempEnv);

前提是这里漏洞百出。您应该使用更安全的字符串函数,例如,如 here. For example, use strnlen 所述,以强制对 path_var 的长度设置一些合理的限制。确保 path_var 在该限制内以 NULL 结尾。使用 strncpy 而不是 strcpy。如有必要,在 strncpy 之后添加 NULL。还有许多其他规则,我没有在此处包括这些规则,因为您的目标似乎是学习而不是生产代码。快乐黑客!