1

In order to better understand the differences between malloc and calloc I tried to find an example where malloc leaves the memory uninitialized/reuses it from a previous allocation.

I came across the SO question Why does malloc initialize the values to 0 in gcc?

I tried to replicate the exampe, but allocating a char array instead and setting a single value. However, it seems malloc works in that case, but why?

Code:

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

int main(void) {
    // this shows, that malloc does not initialize memory
    {
        double *a = malloc(sizeof(double)*100);
        *a = 100;
        printf("%f\n", *a);
        free(a);
    }
    {
        double *a = malloc(sizeof(double)*100);
        printf("%f\n", *a);
        free(a);
    }

    // tried the same with chars, but my example doesn't work
    {
        char *ptr = malloc(sizeof(char) * 10);
        ptr[0] = 'a';
        printf("%s\n", ptr);
        free(ptr);
    }

    {
        char *ptr = malloc(sizeof(char) * 10);
        printf("%s\n", ptr);
        free(ptr);
    }

    return 0;
}

Output:

$ clang -ggdb memset_test.c
$  ./a.out
100.000000
100.000000
a
<empty string>

I can't see the difference, why does the first exable using doubles work, but not mine?

Community
  • 1
  • 1
Max
  • 15,693
  • 14
  • 81
  • 131
  • What do you mean by "malloc() works"? What is it doing that you are expecting/not expecting? – PC Luddite Sep 26 '15 at 06:11
  • 1
    It's undefined behaviour to access uninitialized data. You really can not expect any specific outcome. Someone else could run the exact same code and get a different result than you. Heck, if you recompile with slightly different flags or add some unrelated code, that can even change the behaviour. – kaylum Sep 26 '15 at 06:11
  • possible duplicate of [Why does malloc initialize the values to 0 in gcc?](http://stackoverflow.com/questions/8029584/why-does-malloc-initialize-the-values-to-0-in-gcc) – PC Luddite Sep 26 '15 at 06:16

3 Answers3

4

That is OS system dependent (as pointed out by @Basile Starynkevit in comment more clearly implementation specific ) . malloc won't zero it out as you know that but OS could do that (which depends clearly on OS).

On my system I get the output as -

 100.000000
 0.000000
 a
 02T               // excat output that I get on my system

But it is clear that we access uninitialized memory . So , UB . So we can't expect any desired output.

ameyCU
  • 16,489
  • 2
  • 26
  • 41
  • oh … allright … I see. I should have tested my example on more then one system, i was just surprised, that the example using a double * showed the described behaviour right out of the box, whereas my char example didn't. Thank you for clearing this up for me. – Max Sep 26 '15 at 06:15
  • @Max Different OS could behave differently in such situation . That's , the possible explanation of it :) – ameyCU Sep 26 '15 at 06:18
  • To again explicitly state this: Reading out uninitialised memory (most likely) invokes undefined behaviour, so never do this. @Max – alk Sep 26 '15 at 06:30
  • It is actually *implementation* specific. It does depend upon the compiler, the standard C library, the operating system, the optimization flags, etc.... On an OS with several `libc` (e.g. my Linux desktop has both [GNU libc](http://www.gnu.org/software/libc/) and [musl-libc](http://musl-libc.org/)...) I could have different behaviors on the *same* OS... – Basile Starynkevitch Sep 26 '15 at 06:30
  • @BasileStarynkevitch I was aware that OS would do this in order to save some important data stored . But this turned out compiler also plays a role in it . – ameyCU Sep 26 '15 at 06:36
1

Try to allocate the same amount of memory as in the first malloc for the double:

char *ptr = malloc(sizeof(char) * 800);

Small memory chunks are treated differently than bigger ones in glibc's malloc implementation, and you should print out the value of the returned pointer in order to see that it is the same memory chunk.

It's the free which may overwrite the former data for internal bookkeeping (list of free memory chunks).

4566976
  • 2,419
  • 1
  • 10
  • 14
0

In each case, the behaviour on dereferencing the pointer after the second malloc() call is undefined.

The core definition of undefined behaviour (yes, the standards do state what they mean by "undefined", as ironic as that may seem) is that anything is permitted to happen. That can include seeming to work as you expect, working in one case as you expect and not in another case, etc.

The reason you might see inconsistent behaviour (two similar examples, but only one of them works as expected) often comes down to how the compiler organises data in memory, how the standard library implementation organises data in memory, how your operating system manages memory (therefore how likely malloc() is to return the last free()d pointer), how much physical memory is available on your host machine, etc etc. These things all interact, and there are no guarantees one way or another.

Peter
  • 35,646
  • 4
  • 32
  • 74