strtok()会覆盖其源字符串

时间:2016-09-25 19:29:32

标签: c bash pointers strtok

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

我的问题是,当我尝试将路径内容复制到finalPath时,我对finalPath所做的任何更改都会反映到路径中。由于代码现在,path只会被设置为“home / user / bin”一次,循环并再次设置为相同的东西,然后tokenizer命中“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, ":");
    }

1 个答案:

答案 0 :(得分:3)

BLUEPIXY是对的:tempEnv对于你的字符串来说还不够大。尝试:

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

并在最后

free(tempEnv);

附带条件这是充满漏洞的。您应该使用更安全的字符串函数,例如,如here所述。例如,使用strnlen强制设置path_var长度的合理限制。确保path_var在该限制内以NULL结尾。使用strncpy代替strcpy。如有必要,在strncpy之后添加NULL。还有许多其他规则,我不在此处,因为您的目标似乎是学习而不是生产代码。快乐的黑客!