【问题标题】:How to free up a char*** memory properly In C so I don't get memory leak如何在 C 中正确释放 char*** 内存,这样我就不会出现内存泄漏
【发布时间】:2014-07-30 09:10:18
【问题描述】:

我得到以下代码

int rows = 123;
int cols = 12;
char ***data = (char ***)malloc(rows * sizeof(char **));
if(data) {
    for(int i = 0; i < num_rows; i++)
    {
        data[i] = (char **)malloc(cols * sizeof(char *));
        if(!data[i])
        {
            for(int j = 0; j < i; j++)
                free(data[j]);
            free(data);
            printf("no memory\n");
            return -1;
        }
    }
}
char randomData[] = "<Inserts random string here everytime>";
for(int row = 0; row < rows; row++) {
     for(int col = 0; col < cols; col++) {
         data[row][col] = (char *) malloc(sizeof(char) * (1 + strlen(randomData)));
         strcpy(data[row][col], randomData);
     }
}

我为此 stackoverflow 编写了这个示例,因为实际代码相似,但 &lt;Inserts random string here everytime&gt; 是从每个 SQL 行和每个列输出的。

我只想做一个像data[row][column]这样的多维数组

完成后如何正确释放它?

我想清除它,我必须先清除第一颗星。 char *

for(int row = 0; row < rows; row++) {
     for(int col = 0; col < cols; col++) {
         free(data[row][col]);
     }
}

然后清理第二颗星char **

for(int row = 0; row < rows; row++) {
     free(data[row]);
}

那我终于可以清除最后的三颗星了char ***

    free(data);

这是你的做法吗?似乎是一个矫枉过正太多免费的..是

for(int row = 0; row < rows; row++) {
     for(int col = 0; col < cols; col++) {
         free(data[row][col]);
     }
}

够了吗?

【问题讨论】:

  • “免费的似乎有点过头了..”,好吧,你有这么多mallocs!每个malloc 都需要一个free 语句。这包括循环内的每一次出现;所以,“是的”。
  • @Jongware 这是否意味着我需要free(data[row][col]);free(data[row]); 我已经知道最后我需要free(data);。有些东西告诉我data[row][col] 似乎可以同时两个 2。再一次,是的,似乎真的data[row][col] 只会清除实际的字符串本身,而不是矩阵本身。我怎么知道我必须做 data[row] 还是 data[col]?因为我的意思是这些只是数字行/列。
  • 绝对。你malloc 他们,所以你也需要free 他们。它尽可能简单。
  • 所以我运行 1 个 malloc,然后 123 个 malloc,然后谁知道 15129 个 malloc 有多少,哈哈。我知道我肯定会错过一些东西。
  • .. 上面说了,你可能想到了malloc (rows * cols * sizeof(char *))。这将行和列都放在一个连续的内存块中。如果行数和列数是静态的,您可以考虑这一点——但您需要“手动”计算行/列索引。

标签: c memory-management memory-leaks


【解决方案1】:

您必须取消分配所有 malloc 的内容。

您最多可以通过编写来保存循环:

for(int row = 0; row < rows; row++) {
     for(int col = 0; col < cols; col++) {
         free(data[row][col]);
     }
     free(data[row]);
}
free(data);

如果你想一次性取消分配,你必须一次性分配,但是对于指针数组来说很棘手,必须用红色闪烁字体注释:

data = malloc(rows * (1 + cols) * sizeof(void *));
for (i=0; i<rows; i++) {
    data[i] = &(data[cols * i]);
}

然后取消分配将是:

for(int row = 0; row < rows; row++) {
     for(int col = 0; col < cols; col++) {
         free(data[row][col]);
     }
}
free(data);

如果你愿意,你可以直接分配一个二维数组:

data = malloc(rows * cols * sizeof(void *));

但是,您必须通过data[j + i * rows] 访问各个元素...才能以红色闪烁字体进行评论...

【讨论】:

  • 哦,哇,你也为我避免了整个循环哈哈,我想既然你是专业人士,我会相信你的回答。
【解决方案2】:

你需要尽可能多地释放你的 malloc

释放整个数组取决于你的数组维度,

让我们先看看你是如何分配这个数组的:

1 - char ***array = char pointer to 2d arrays (A)

2 - **array= char pointer to 2d array         (B)

3 - *array= char pointer to (vector) of char  (C)

如果你有 ***array,你需要开始:

1 - freeing each vector of your inner array (C)
2 - freeing inner array pointer             (B)                  
3 - freeing the main pointer                (A)

对于您的示例,您可以这样做:

for(int row = 0; row < rows; row++) {
    for(int col = 0; col < cols; col++) {
        free(data[row][column]);
    }
    free(data[row]);
}
free(data);

【讨论】:

    【解决方案3】:

    malloc 的每次调用都需要对free 的一次调用。您已经概述了释放所有分配的正确 (!) 方法。 frees 的数量应该不是问题(毕竟你对malloc 的调用次数完全相同没有问题)。

    如果你想测试确定,添加一些低级调试代码:

    1. 在例程顶部添加一个整数 int number_of_allocations = 0;
    2. 在每个malloc 之后增加它。
    3. 在每个free 之后递减
    4. 测试最终结果是否为 0。

    据我所知,那里应该没有泄漏。

    【讨论】:

    • 哈哈,是的,我通过简单的数学知道我做了多少 malloc,但我只是不想释放我已经释放的那些。
    • 你做对了:按照相反的分配顺序。不用担心。
    • 我真的很感谢你的帮助,你真的让我的神秘逻辑更加可靠,我会接受你的答案是最好的,但我现在使用的 Serge 的代码也优化了一个循环,我完全错过了这似乎与我真正寻找的其他一切相吻合。谢谢,我给了你一个加号。虽然它确实有语法错误lol
    猜你喜欢
    • 2020-09-19
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    • 1970-01-01
    • 2011-06-28
    • 2012-06-08
    • 2017-04-24
    相关资源
    最近更新 更多