我已经看到了另一个分配和freeing多维数组的问题,但我怀疑它没有正确释放。为了测试,我从主代码中提取了这个小代码。 我使用XCode或gcc 4.9在MacOS X.10下编译它,结果相同:
它运行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;
}
我是新手所以我怀疑我的解放是不正确的......
在你的帮助下我更正了我的代码,它现在已经纠正,并且在ram中只需要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;
}
答案 0 :(得分:2)
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));
这里分配的内存比以后在程序中释放的内容要多。
将raf09_grid.lonSize
中的get_raf09_grid()
变量更新为等于nbElLon
,并解决问题。
通常,每个malloc
都应该有相应的free
。一旦你知道哪个malloc
正在泄漏,那么你可以找到应该释放该变量的代码,并从那里进行调试。
注意:我将循环从20000减少到1000,但它会给你相同的信息。
答案 1 :(得分:2)
在阅读了yoiur问题之后,这里有一些建议:
在代码中:
for(i=0;i<420;i++) {
for(j=0;j<380;j++) {
raf09_grid.grid[i][j]=0.0;
}
您正在循环i
和j
420和380,而您已定义:
int nbElLat=381;
int nbElLon=421;
所以,你永远不会处理经度的第420次迭代。同样在Latitude的第380个循环中错过了。 如果这是一件令人向往的事情,那就好了,否则你应该把它修好为:
for(i=0;i<nbElLon;i++) { //better use macros or variable names than just plain magic numbers
for(j=0;j<nbElLat;j++) {
raf09_grid.grid[i][j]=0.0;
}
其次,在free_raf09_grid()
函数中,您使用:
for (i = 0; i < raf09_grid.lonSize; ++i) {
但你还没有在任何地方初始化该变量。
可能在get_raf09_grid()
声明之前的函数int i,j
执行此操作:
raf09_grid.lonSize = nbElLon;
raf09_grid.latSize = nbElLat;
第三个重要的一个。 在下面的行中:
raf09_grid.grid = malloc(nbElLon*sizeof(double*));
int it;
for(it=0;it<nbElLon;it++)
raf09_grid.grid[it] = malloc(nbElLat*sizeof(double));
您应该检查malloc
是否已成功返回,并检查是否为空。
答案 2 :(得分:1)
你的for循环使用lonSize作为参数,但它不会在任何地方更新