2

If I'm allocating memory in a loop like so

for(file = 0; file < nfile; file++){
...
...
...
   for(yy = 0; yy < ngridy; yy++){
      for(xx = 0; xx < ngridx; xx++) {
         tmparr1[xx+(ngridx*yy)] = (double *)calloc(nptperf[file], sizeof(double));
         tmparr2[xx+(ngridx*yy)] = (double *)calloc(nptperf[file], sizeof(double));
      }
   }

Sometime later in the code I'm freeing memory like so :

for(yy = 0; yy < ngridy; yy++){
    for(xx = 0; xx < ngridx; xx++) {
       free(tmparr1[xx+(ngridx*yy)]);
       free(tmparr2[xx+(ngridx*yy)]);
    }
}

Would there be a possibility of free() not freeing the memory and hence causing a whole lot more memory to be allocated? I'm allocating and freeing the memory once every file loop. Also, nptperf[file] is usually around 1-3 million points, and ngridx = ngridy = 100.

This program works for ngridx = ngridy = 80 and less, but fails at 100.

Kitchi
  • 1,874
  • 4
  • 28
  • 46
  • free takes a void *ptr as argument and you are passing an array? – Bhavik Shah Nov 08 '12 at 09:01
  • 1
    First compile your program in debug mode using --ggdb option of gcc then use `valgrind --leak-check=full --show-reachable=yes ./programname` to find the critical points where you are leaking memory – linello Nov 08 '12 at 09:03
  • @BhavikShah - Yeah... tmparr1 is defined as `double **tmparr1` so I'm passing an array to free. – Kitchi Nov 08 '12 at 09:25

4 Answers4

3

You are using wrong variables inside the bodies of your loops (gg and ggy instead of xx and yy). Among other problems, this causes (almost) all of the allocated memory to be leaked since you're losing the calloc()ed pointers.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • I've changed it, still get the same problem! Thanks for pointing that out. Can't believe I missed it. – Kitchi Nov 08 '12 at 09:23
  • @Kitchi: 3 million points on a 100x100 grid will require almost half a terabyte of memory for the two arrays. Does your box have enough RAM/swap? – NPE Nov 08 '12 at 09:26
  • That's what I figured... but I wanted to make sure that it wasn't a memory leak either. I've only got 50 GB combined memory+swap. So every time I run it, my process is `killed` by linux. – Kitchi Nov 08 '12 at 09:47
  • I just noticed something - even when my program works (with `ngridx = ngridy = 50`, I need some `74 GB` of space to allocate ~4 million double precision numbers on my `50x50` grid. But my physical ram is only `16GB` and if I monitor the memory usage, it peaks only at about `60%` or so. I'm very confused about why my program is running. – Kitchi Nov 08 '12 at 16:47
  • How much swap space do you have? – NPE Nov 08 '12 at 16:53
  • `32 GB`. But I thought that swap was only accessed when the RAM was full? – Kitchi Nov 08 '12 at 16:55
  • 1
    To be honest, I don't see how 50x50x4,000,000 doubles can fit in 16+32GB. If you'd like to figure it out, I'd suggest producing a small self-contained runnable example, and posting it as a separate question along with your observations. – NPE Nov 08 '12 at 16:57
1

There are two possibilities:

  1. free() can fail meaning you don't free the memory you used (your question)
  2. your program has a bug and you don't free the memory you used, you are leaking memory.

The first is unlikely to happen, I don't know of any circumstances where free() fails if used properly. If it is passed the proper pointer, that memory will be freed, if it is passed NULL, it will do nothing.

The second is more likely to happen, but in the above snippet it looks ok. As mentioned above you can use Valgrind (/ˈvælɡrɪnd/) to check if something is going wrong. Compile with -O0 -ggdb and have Valgrind check the allocation and deallocation.

Tim
  • 1,466
  • 16
  • 24
0

Run a tool like Valgrind with your program and see if you are leaking any memory. From the code you have posted, it does not look like you are leaking memory. But using Valgrind will confirm that and also it can point out other problems which may exist.

CCoder
  • 2,305
  • 19
  • 41
0

It is possible that the program may be running out of memory, calloc returning a null, ensued by memory corruption and finally getting killed.

I would suggest checking for the return value from calloc instead of assuming that it succeeded.

If the program needs a lot memory, make sure there is enough swap space to handle the requirements. Remember that there are possibly other apps running on the system as well.

The other option is to divide and conquer. One possibility is to turn it into a distributed application running on multiple machines. Without knowing what the rest of the application does, this may or may not be feasible.

Arun Taylor
  • 1,574
  • 8
  • 5