5

I was curious about what exactly a pointer holds, after malloc() was used to allocate memory space? The manpage tells me that calloc() initializes the allocated memory space with zero.

The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().

and

The calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().

I created a really short example program in C, to C(haha) for myself:

int main() {
    char *dynamic_chars;
    unsigned amount;
    printf("how much bytes you want to allocate?\n");
    scanf("%d", &amount);

    dynamic_chars = (char*)malloc(amount*sizeof(char));
    printf("allocated:\n%s\n", dynamic_chars);

    free(dynamic_chars);
    return 0;

}

However when executing this code, it just outputs nothing. If I initialize the memory my self for example initializing every single byte with 0xFFFF using a loop, then the program shows me exactly what I expect. The memory space actually exists, since I wont get an error claiming that I am trying to access uninitialized variables or so.

Since memory space is usually not deleted but marked as rewritable I wonder if by executing my program, shouldn't I be able to see random previously used Bytes of memory? But I wont see anything, so I am really confused about how exactly malloc() works.

EDIT1

Another thing about malloc() or maybe memory usage in general, that is interesting about my program: If I use calloc(), to allocate memory, I can trace the actual memory usage of my program, by e.g. monitoring it. For example, if I tell my program, to allocate 1.000.000.000 Bytes of memory per calloc() I will see the following in my System monitor: Memory consumption when using <code>calloc()</code>

As you can probably imagine, when using malloc(), I wont see nothing. I understand, that just by allocating memory, I am not really using it at that time, but I am still confused about why my operating system (unix derivate) won't recognize it as being used. Since malloc() just like calloc() returns a physical address to a memory location I don't get, how this memory area seems to be not actually reserved by the OS. Elsewise I could see it in the System Monitor right? If I should rather post this as a new question, please let me know. But I think since the question is still about how malloc() works it fits in here.

Julian
  • 525
  • 5
  • 19
  • Tends to be 0 by accident when you test it like this. That won't repeat well when you do it in a real program and previously freed heap blocks are getting recycled. You are not allowed to make any assumptions. – Hans Passant May 12 '16 at 10:53
  • 2
    If the memory begins with zero, `printf` takes it as `""` (zero being the terminaison caracter) You should use another method if you want to see the real values. – Gwen May 12 '16 at 10:54
  • `scanf("%d", &amount);` → `scanf("%u", &amount);` – Spikatrix May 12 '16 at 11:40
  • I think the answer to "edit 1" part of your question is probably implementation/os specific, but since calloc requires contiguous memory and malloc can use fragments, it is possible that malloc can use memory already allocated for your program while calloc needs to reserve "new" memory. Or malloc can postpone the actual reservation until the time the memory is actually used. – diidu May 12 '16 at 12:18
  • Note: Why use type `unsigned amount;`? Review the paramter type accepted by `malloc()`. – chux - Reinstate Monica May 12 '16 at 12:25

3 Answers3

13

No, malloc() returns uninitialized memory, the contents of which is indeterminate. So, attempt to use the value invokes undefined behavior.

Quoting C11, annex §J.2, Undefined behavior

The value of the object allocated by the malloc function is used

In this case, %s expects a null-terminated char array. However, the content of dynamic_chars is indeterminate, so there may very well be no null-terminator, at all, which will cause the out-of-bound memory access, which in turn invokes the UB.

Quoting C11, chapter §7.22.3.5, The malloc function (emphasis mine):

The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.

That said, please see this discussion on why not to cast the return value of malloc() and family in C..

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Not to be confused with [realloc](http://www.cplusplus.com/reference/cstdlib/realloc/) that initializes the allocated memory! – gsamaras May 12 '16 at 10:57
  • @gsamaras I thought the question is specific about `malloc()`, isn't it? :) – Sourav Ghosh May 12 '16 at 10:57
  • Sourav sure, but it was just some says before that a new-comer was confused with these two. Maybe I should delete my comments? – gsamaras May 12 '16 at 10:59
  • @gsamaras Not at all, It's helpful, nonetheless. Let both our comments be there. :) – Sourav Ghosh May 12 '16 at 11:00
  • OK, now, reason behind downvote, anybody? What did I miss? – Sourav Ghosh May 12 '16 at 11:06
  • Why would *reading* uninitialized memory lead to undefined behavior? You get an undefined result (as far as the specification is concerned), but surely the *behavior* is as it should be? – Jongware May 12 '16 at 11:08
  • 3
    @RadLexus reading indeterminate values as `char` may produce a trap representation. But even on systems with no trap representations, passing an indeterminate value to a library function such as `printf` is not defined. [See here](http://stackoverflow.com/a/25074258/1505939) for further discussion – M.M May 12 '16 at 11:19
  • 1
    @RadLexus Just to add a bit more context, C11 specifically mentions this case as UB. Please note the edit in my answer. – Sourav Ghosh Jun 17 '16 at 20:03
2

malloc allocates the memory for you and sets pointer to it. It does not initialize the memory in any way, so the allocated memory area can contain anything. Since it does not contain a string, you can't read it's content by printing a string. Instead you could print it byte by byte, like this:

for(int i=0;i<amount*sizeof(char);i++)
{
    printf("%02x", (unsigned)dynamic_chars[i]);
}
diidu
  • 2,823
  • 17
  • 32
  • 1
    This passes indeterminate values to a library function. The C standard is unclear about this but [DR451 Proposed Committee Resolution](http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_451.htm) recommends that this be undefined behaviour – M.M May 12 '16 at 11:22
  • @M.M I don't understand why this code should be a problem. The values in `dynamic_chars` are certainly underterminate, but they are still just values and I don't see why it should be a problem to print the hexadecimal representation of these values. – Jabberwocky May 12 '16 at 11:28
  • @M.M good point on the %x, I made small improvement to fix it. However I have difficulty in understanding why would the behaviour of printf be undefined, the content definitely is (as mentioned by Michael Walz), but I don't understand why wouldn't it be possible to print out the content of the memory. – diidu May 12 '16 at 11:34
  • uninitialized memory doesn't have any contents, in Standard C. It sounds like you're imagining that it contains some value – M.M May 12 '16 at 11:36
  • 2
    @M.M ok I agree with you from the spec point of view. However, in practice for uninitialized memory not to contain any value, it would need to be unexisting memory before it is initialized. Have you even seen an implementation like that? I have not and I can not even imagine one. – diidu May 12 '16 at 11:42
  • In any case it should be safe to say that reading uninitialized memory like that is ok for study or debugging purposes, but may be unsafe for production. – diidu May 12 '16 at 11:43
2

It's undefined by the C language what the memory block contains when you get it. In practice it will most likely simply contain what was in that physical memory previously.

If the memory was previously used by your program and freed you'll likely just get what was in it before. If it's memory newly requested from the operating system you'll get what the operating system put in it. Most operating systems return memory that has been specifically set to 'zero' bytes because it would be a security issue if the memory still contained what was in it from some other program previously.

None of that is guaranteed by any standard, it's just what most systems do in practice.

jcoder
  • 29,554
  • 19
  • 87
  • 130