c - 在 C 中释放 malloc 字符串的二维数组失败

标签 c multidimensional-array memory-leaks malloc free

我知道这是一个经常被问到的问题,但我已经阅读了 10 多个已关闭的问题,但没有任何运气,因为我的解决方案似乎与其他人提出的解决方案相匹配。

我正在编写自己的 shell 作为学习练习,在这样做的过程中,我分配了一个字符串数组作为程序调用的参数。我的 malloc 完成如下,其中 argcnt 是给定的参数数量 + 2 以匹配标准 argv 大小并允许数组以 null 终止并因此被 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)

在过去的 2 个小时里,我一直在努力解决这个问题,但无法找出问题所在,因此非常感谢对问题的一些深入了解。

编辑: 当前破坏我的程序的函数是:

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 的返回值分配给指针变量时,您会用新值覆盖该变量的指针值。这意味着,如果该指针变量指向您已经分配的内存,则该内存将“泄漏”,因为您不再有指向它的指针。

简而言之 - 如果您为指针变量分配内存,请不要为该指针变量分配不同的值,除非您已经释放内存或将指针值放在其他地方。

在您的 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); 您还应该在从 strcpy 中检查 tok 是否为 NULL。

        i++;
    }
    args[i] = '\0';

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

    free(tok);

不要在此处释放 tok,因为在此阶段 tok 应该为 NULL,但您确实需要 free (str)

}

另请注意其他一些关于检查您处理的参数是否超过内存限制(例如每项 80 个字符)的评论。

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

相关文章:

c - double 与 int 相乘时变为 0

c - 将c语言映射为汇编语言

C 代码来查明数字是否为 "strong"(来 self 的语言的直译)

php - CSS 中的多维数组 PHP

c++ - 将二维数组传递给函数而不指定第二维时出现编译器错误

ios - Xcode 4.2.1 : UIPickerView causing memory leak, 使用 ARC

c - C 结构中的默认值

javascript - 测试未初始化的数组元素不起作用

delphi - TWebbrowser 大量内存泄漏 : no solution so far

java - Java中的已用和空闲内存