C 在结构中释放多维数组似乎不正确

标签 c memory-management memory-leaks malloc free

我看到了另一个关于分配和 freeing 的问题多维数组,但我怀疑它没有正确释放。为了测试,我从我的主要代码中提取了这个小代码。 我在 MacOS X.10 下使用 XCode 或 gcc 4.9 编译了它,结果相同:

错误代码

它运行了 200000 次,内存消耗增长到 20GB!:

#include <stdlib.h>
typedef struct{
    int lonSize;
    int latSize;
    double **grid;
}raf09_grid_t;
static raf09_grid_t raf09_grid;

void free_raf09_grid() {
    if (raf09_grid.grid != NULL) {
            int i;
                for (i = 0; i < raf09_grid.lonSize; ++i) {
                    free(raf09_grid.grid[i]);
                }
                free(raf09_grid.grid);
    }
    raf09_grid.latSize = 0;
    raf09_grid.lonSize = 0;
}

void get_raf09_grid() {
    int nbElLat=381;
    int nbElLon=421;
    raf09_grid.grid = malloc(nbElLon*sizeof(double*));
    int it;
    for(it=0;it<nbElLon;it++)
          raf09_grid.grid[it] = malloc(nbElLat*sizeof(double));
    int i,j;
    for(i=0;i<420;i++) {
        for(j=0;j<380;j++) {
           raf09_grid.grid[i][j]=0.0;
        }
    }
}

int main (int argc, char *argv[]) {
   int i=0;
   for (i=0;i<20000;i++) {
       get_raf09_grid();
       free_raf09_grid();
   }
   return 0;
}

我是新手,所以我怀疑我的释放不正确......

更正代码

在您的帮助下,我更正了我的代码,它现在是正确的并且只占用 10M 内存:

#include <stdlib.h>
typedef struct{
    int lonSize;
    int latSize;
    double **grid;
}raf09_grid_t;
static raf09_grid_t raf09_grid;

void free_raf09_grid() {
    if (raf09_grid.grid != NULL) {
            int i;
                for (i = 0; i < raf09_grid.lonSize; ++i) {
                    free(raf09_grid.grid[i]);
                }
                free(raf09_grid.grid);
    }
    raf09_grid.latSize = 0;
    raf09_grid.lonSize = 0;
}

void get_raf09_grid() {
    raf09_grid.latSize=381;
    raf09_grid.lonSize=421;
    raf09_grid.grid = malloc(raf09_grid.lonSize*sizeof(double*));
    int it;
    for(it=0;it<raf09_grid.lonSize;it++)
          raf09_grid.grid[it] = malloc(raf09_grid.latSize*sizeof(double));
    int i,j;
    for(i=0;i<420;i++) {
        for(j=0;j<380;j++) {
           raf09_grid.grid[i][j]=0.0;
        }
    }
}

int main (int argc, char *argv[]) {
   int i=0;
   for (i=0;i<20000;i++) {
       get_raf09_grid();
       free_raf09_grid();
   }
   return 0;
}

最佳答案

Valgrind 是跟踪内存泄漏的宝贵工具。使用调试信息编译您的源代码,并运行它:

valgrind --leak-check=full -v ./a.out

将给出以下总结:

==7033== HEAP SUMMARY:
==7033==     in use at exit: 1,283,208,000 bytes in 421,000 blocks
==7033==   total heap usage: 422,000 allocs, 1,000 frees, 1,286,576,000 bytes allocated
==7033== 
==7033== Searching for pointers to 421,000 not-freed blocks
==7033== Checked 92,040 bytes
==7033== 
==7033== 18,288 bytes in 6 blocks are possibly lost in loss record 1 of 2
==7033==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7033==    by 0x400611: get_raf09_grid (grid.c:27)
==7033==    by 0x4006A8: main (grid.c:39)
==7033== 
==7033== 1,283,189,712 bytes in 420,994 blocks are definitely lost in loss record 2 of 2
==7033==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7033==    by 0x400611: get_raf09_grid (grid.c:27)
==7033==    by 0x4006A8: main (grid.c:39)
==7033== 
==7033== LEAK SUMMARY:
==7033==    definitely lost: 1,283,189,712 bytes in 420,994 blocks
==7033==    indirectly lost: 0 bytes in 0 blocks
==7033==      possibly lost: 18,288 bytes in 6 blocks
==7033==    still reachable: 0 bytes in 0 blocks
==7033==         suppressed: 0 bytes in 0 blocks
==7033== 
==7033== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)
--7033-- 
--7033-- used_suppression:      2 dl-hack3-cond-1
==7033== 
==7033== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)

第27行的链接表明这条语句有问题:

raf09_grid.grid[it] = malloc(nbElLat*sizeof(double));

您在这里分配的内存多于程序稍后释放的内存。

get_raf09_grid() 中的 raf09_grid.lonSize 变量更新为等于 nbElLon,它解决了问题。

一般来说,每一个malloc都应该有一个对应的free。一旦您知道哪个 malloc 正在泄漏,您就可以找到应该释放该变量的代码,并从那里进行调试。

注意:我将循环次数从 20000 减少到 1000,但它会为您提供相同的信息。

关于C 在结构中释放多维数组似乎不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25227917/

相关文章:

c - 我想构建一个具有整数输入的函数,将其输出存储到全局字符数组

mysql - MariaDB max_heap_table_size 是动态分配的吗?

iphone - CGImage 中的内存泄漏

objective-c - SubstringWithRange NSString 内存泄漏

arrays - 如何用C实现埃拉托色尼筛法算法?

c - EXC_BAD_ACCESS 的 minishell malloc 错误

c - 在 C 中使用省略号传递参数

修剪时 realloc 会失败(返回 NULL)吗?

c++ - 开发中如何避免 "swapping of death"?

ruby-on-rails - 在 Ruby on Rails 项目中查找内存泄漏