我知道这是一个经常被问到的问题,但我读了10个以上的封闭式问题,没有任何运气,因为我的解决方案似乎与其他人提出的解决方案相匹配。
我正在编写自己的shell作为一个学习练习,在这样做的过程中,我将一个字符串数组作为程序调用的参数。我的malloc如下所示,其中argcnt是给定的参数数+2,以匹配标准argv大小,并允许数组以空结尾,从而由execvp使用:

char ** args;
args = (char **) malloc(argcnt*sizeof(char *));
for(i = 0; i < argcnt; i++) {
    args[i] = (char *) malloc(80*sizeof(char));
    printf("Made %d\n", i);
}

然后我释放相同的记忆如下:
for (i = 0; i < argcnt; i++) {
    free(args[i]);
    printf("Freed %d\n", i);
}
free(args);

程序进行编译,但在运行时无法释放argv[1]。运行程序然后调用ls -a -l的示例输出如下:
jack@ubuntu:~/myshell$ ./myshell
[30/03 23:34] # ls -a -l
Argcnt: 4
Made 0
Made 1
Made 2
Made 3
Arg[0]: ls
Arg[1]: -a
Arg[2]: -l
Arg[3]: (null)
Freed 0
*** Error in `./myshell': free(): invalid pointer: 0x0000000001a84c43 ***
Aborted (core dumped)

在过去的两个小时里,我一直在纠结这个问题,不知道出了什么问题,所以对这个问题的一些见解将是非常感激的。
编辑:
当前中断我的程序的功能是:
void breakargs(char * cmd, char ** args) {
    char * tok = malloc(strlen(cmd)*sizeof(char)); //maximum token size is full cmd
    char * str = malloc(strlen(cmd)*sizeof(char));
    int i=1;
    strcpy(str, cmd); //maintains integrity of cmd

    args[0] = tok = strtok(str, " ");
    while (tok != NULL)
    {
        args[i] = tok = strtok(NULL, " ");
        i++;
    }
    args[i] = '\0';
    free(tok);
}

第二次编辑:问题是我用strtok重新分配了原来malloc所做的指针,这样原来的指针引用就丢失了。此外,我对参数使用一定的字符串长度可能会导致问题。解决方案是,当我知道需要存储在那里的字符串的长度时,只使用malloc args[i],然后使用strcpy将字符串移动到该内存位置,而不是像我一直在做的那样直接赋值。这将保持指针引用的完整性,并允许正确释放指针引用。

最佳答案

strtok将指针返回到最初传递给strtok的字符串中,不需要为该指针分配空间。
将返回值strtok赋给指针变量时,将用新值覆盖该变量的指针值。这意味着,如果指针变量指向您已经分配的内存,则该内存将“泄漏”,因为您不再有指向它的指针。
简而言之-如果为指针变量分配内存,不要为该指针变量分配不同的值,除非您已经将内存freed或将指针值放在其他地方。
breakArgs函数中有许多问题:

void breakargs(char * cmd, char ** args) {
    char * tok = malloc(strlen(cmd)*sizeof(char)); //maximum token size is full cmd

您不需要为tok分配内存,因为您将从strtok为其分配一个值
    char * str = malloc(strlen(cmd)*sizeof(char));
    int i=1;
    strcpy(str, cmd); //maintains integrity of cmd

    args[0] = tok = strtok(str, " ");

不要直接分配到args[0]中,因为这将覆盖指向已分配内存的指针。而是分配到tok,然后strcpy(args[0], tok);
    while (tok != NULL)
    {
        args[i] = tok = strtok(NULL, " ");

不要直接分配到args[i]中,因为这将覆盖指向已分配内存的指针。而是分配到tok,然后strcpy(args[i], tok);
您还应该在从中tok之前检查strcpy是否为空。
        i++;
    }
    args[i] = '\0';

不要直接赋给args[i],而是可以用strcpy(args[i], "")来表示结尾,这样结尾就有一个空字符串。
    free(tok);

不要在这里释放tok,因为到这个阶段tok应该是空的,但是您确实需要free (str)
}

还要注意其他一些关于检查处理的参数是否不超过内存限制(例如,每个项80个字符)的注释。

关于c - 在C中释放malloc字符串的二维数组失败,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36320994/

10-10 09:21