4

Here is a very simple program I wrote to show the differences between the valgrind outputs on Mac (El Capitan) and Linux Mint 17.2.

Is there a way get the same type of output on the mac? I dont understand why it shows more heap usage on the mac than it does on Linux?

For a strange reason Linux Mint shows the memory being freed, whereas OSX doesn't

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char const *argv[]) {

  char *str = (char *)malloc(15);
  strcpy(str, "Hello World!");
  printf("%s\n", str);
  free(str);
  return 0;
}

Linux Mint 17.2 Linux Mint

Mac OSX El Capitan MacOSX

Community
  • 1
  • 1
RandomMath
  • 675
  • 15
  • 33
  • Because it is a newer version? – MikeCAT Mar 01 '16 at 14:54
  • @MikeCAT - Why would that make a difference? My issue is that it doesn't show or say that the memory is being freed (all heap freed) – RandomMath Mar 01 '16 at 14:57
  • An environment may allocate some blocks from the heap for internal structures (for example stdio-handles or similar). It is ok not to free them, since they are reclaimed by the os automatically on process termination. This is _not_ considered a memory leak. A leak increases over time. – Ctx Mar 01 '16 at 14:58
  • I'd guess that the startup code (the stuff running before `main`) on OS X is allocating data which is not free'd after `main` returns because it's free'd either way on process termination. valgrind detects these "missing" frees, but obviously knows that they're not an issue (0 errors shown) – Daniel Jour Mar 01 '16 at 14:59
  • @DanielJour - Is there a configuration that can be made so it can display differently? – RandomMath Mar 01 '16 at 15:00
  • @RandomMath I don't know whether you can suppress the ... eh ... suppressed errors. A quick search seems to say it's not possible. – Daniel Jour Mar 01 '16 at 15:01
  • maybe because OSX is BSD based and Linux is NOT so the implementations are guaranteed to be completely different? –  Mar 01 '16 at 15:03
  • http://stackoverflow.com/a/8657357/1579327 – Paolo Mar 01 '16 at 15:04

2 Answers2

3

The C standard library and runtime do stuff before main is called, and printf also does stuff internally. This "stuff" may include memory allocations. This is implementation-specific, so it's no surprise that completely different implementations show different amount of allocations.

Then, when program exits, it might not actually be necessary to free any heap allocations, because when process terminates, the heap will be gone, poof, removed by the OS (in a desktop operating system like both of above are). The application code should free all memory it allocates (because of portability, and because then you can actually use tools like valgrind, and because it's "clean"). But for platform and compiler specific library code, it would just slow down the exit of every program, for no gain. So library not doing it is basically an optimization, which you normally shouldn't do in your own program (unless you can actually measure that it makes a difference somewhere).

So tools like valgrind generally contain suppression lists for known un-freed memory blocks. You can also configure your own suppression lists for any libraries which you use, and which don't release all memory on program exit. But when working with suppressions, better be sure you are suppressing safe cases, and not hiding actual memory leaks.


Speculation: Because here the difference in number of allocations is quite big, one might hazard a guess, that Linux implementation uses only static/global variables, where Mac implementation also uses heap allocations. And the actual data stored there might include things like stdin/stdout/stderr buffers. Now this is just a guess, I did not check the source code, but the purpose is to give an idea of what the allocations might be needed for.

hyde
  • 60,639
  • 21
  • 115
  • 176
2

You need to learn how to interpret the results, especially on Mac OS X.

Your Mac output says (I wish I didn't have to type this — dammit, screen images are such a pain!):

definitely lost: 0 bytes in 0 blocks
indirectly lost: 0 bytes in 0 blocks
  possibly lost: 0 bytes in 0 blocks
still reachable: 0 bytes in 0 blocks
     suppressed: 26,091 bytes in 184 blocks

That means what it say — you have no memory leaks. The suppressed stuff is from the Mac C runtime library start-up code. It allocates quite a lot of space (most of 26 KiB on your machine, with 184 separate allocations) and doesn't explicitly free it before the program executes. That's why they're suppressed — they're not a fault of your program, and there's essentially nothing you can do about it. That's the way of life on Mac. FWIW, I just ran a program of mine and got:

==57081== 
==57081== HEAP SUMMARY:
==57081==     in use at exit: 38,858 bytes in 419 blocks
==57081==   total heap usage: 550 allocs, 131 frees, 46,314 bytes allocated
==57081== 
==57081== LEAK SUMMARY:
==57081==    definitely lost: 0 bytes in 0 blocks
==57081==    indirectly lost: 0 bytes in 0 blocks
==57081==      possibly lost: 0 bytes in 0 blocks
==57081==    still reachable: 0 bytes in 0 blocks
==57081==         suppressed: 38,858 bytes in 419 blocks
==57081== 
==57081== For counts of detected and suppressed errors, rerun with: -v
==57081== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

I don't know why I have 12 KiB more space and 235 more allocations from the run-time system than you do. However, this is absolutely the normal behaviour on Mac.

If there's a major upgrade to the o/s, the old suppressions may stop being effective, and you may suddenly get a whole lot more 'still reachable' or other memory 'problems'; at that point, you examine the reports carefully and then generate new suppressions. I have a file with 84 suppressions in it that I was using at one point — then I got a new version of Valgrind and they were already in place.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278