0

I created a small test in order to create memory leaks and testing the leaks in terminal using leaks command. Now I encountered a strange behavior with the NULL. So any explanation why the other code leaks, and the other one doesn't? Aren't they really the same?


int     main(void)
{
    char *ptr;
    char *btr;

    ptr = NULL;
    btr = (char*)malloc(4);
    btr = ptr;
    while (1)
        ;
    return (0);
}
    // LEAKS

int     main(void)
{
    char *btr;

    btr = (char*)malloc(4);
    btr = NULL;
    while (1)
        ;
    return (0);
}
    //NO LEAKS ?? why

2 Answers2

1

If anything I would hazard that you have compiler optimisation turned on. In the second example this will likely ignore the line

btr = (char*)malloc(4);

during compilation as you immediately set the result to NULL.

ChrisBD
  • 9,104
  • 3
  • 22
  • 35
  • Is it allowed to do that? Isn't it supposed to call `malloc` for its side effects? – Ian Abbott Dec 02 '19 at 16:27
  • Further to my comment above [5.1.2.3p4](http://port70.net/~nsz/c/c11/n1570.html#5.1.2.3p4) says "In the abstract machine, all expressions are evaluated as specified by the semantics. An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that **no needed side effects** are produced (including any caused by calling a function or accessing a volatile object)." (emphasis mine). But I wonder what criteria determine whether a side effect is _needed_? – Ian Abbott Dec 02 '19 at 16:34
  • gcc does indeed optimize out the call to `malloc` and it seems to be solely based on the function name matching a built-in function name, regardless of whether `` has been `#include`d or not. – Ian Abbott Dec 02 '19 at 16:47
  • Adding the `-fno-builtin` option to the gcc command line prevents it from optimizing out the call to `malloc`. – Ian Abbott Dec 02 '19 at 16:52
  • Hmm. No effect with -fno-builtin or -O0, but if I add printf("%p",ptr) after btr = NULL; it will then show the leak. But compiler optimization seems a reasonable cause. – sluhtala Dec 02 '19 at 17:08
0

Unfortunately I can't comment, but some people have commented that it would the result of compiler optimization.

However, if we copy the original non-leaky code and change the value to a larger number, we can clearly see that it is allocating memory:

int     main(void)
{
    char *btr;

    btr = (char*)malloc(1000000);
    btr = NULL;
    while (1)
        ;
    return (0);
}

Leaks output:

Process 9945: 162 nodes malloced for 994 KB
Process 9945: 0 leaks for 0 total leaked bytes.

If we comment the allocation out:

Process 10070: 161 nodes malloced for 14 KB
Process 10070: 0 leaks for 0 total leaked bytes.

So clearly the allocation does happen and leaks is aware of it (+1 node, +circa 1 MiB). If the compiler (clang, Hive Mac default settings, no special flags) has supposedly optimised it out, how can leaks know about the allocation?