0

As far as I know, malloc does not initialize the allocated memory. However, on macOS arm64, all values appear as zero. Why does this phenomenon occur? Is this related to ASLR?

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

int main(int argc, const char * argv[]) {
    int *ptr = malloc(sizeof(int) * 100);
    for (int idx = 0; idx < 100; idx++) {
        printf("%d\n", ptr[idx]); // 0
    }
    free(ptr);
    return 0;
}
(lldb) memory read 0x126004f70 --size 4 --count 100 -f d
0x126004f70: 0
0x126004f74: 0
0x126004f78: 0
0x126004f7c: 0
0x126004f80: 0
0x126004f84: 0
0x126004f88: 0
0x126004f8c: 0
0x126004f90: 0
0x126004f94: 0
0x126004f98: 0
0x126004f9c: 0
...
5
  • 5
    a) because the implementation decided to for security reasons. b) because it was already 0. The C standard does not require it: use calloc. it might have happened even before malloc was called: MSVC typically provides a C executable with 2GB of memory for code, stack, heap, everything, and some other implementation might zero the lot before execution begins. Commented Jan 29 at 19:22
  • 2
    ... it might also be because you compiled/linked a debug version, which might have a repeatable memory layout. Commented Jan 29 at 19:29
  • see here and here Commented Jan 29 at 19:49
  • From the compilers perspective, you are reading uninitialized memory so the compiler is free to replace printf("%d\n", ptr[idx]); with printf("0\n"); (or any number) if it wants to - even if the memory returned by malloc contains indeterminate values. Commented Jan 29 at 19:55
  • ...running a simple MSVC program that mallocs most of the memory: it is all 0. How tragic if it reveals personal data or activity from previous usage. It's a C requirement only, for efficient code. Commented Jan 29 at 20:21

4 Answers 4

5

You see zeros because your process had not previously used the memory that malloc allocated for you, so that memory contained the contents that were in it when the operating system provided it to your process. macOS, like all general-purpose multi-user systems, initializes general memory allocations to zero. That is largely for security, to ensure no private data from other processes or system software is visible in the memory given to your process. (There are specific types of allocations that do not initialize the memory to zero, like mapping a file into memory.)

If you write non-zero data to the memory, release it with free, and do another allocation where malloc returns the same memory as before, you will likely see the memory does not contain zeros.

Sign up to request clarification or add additional context in comments.

Comments

3

As far as I know, malloc does not initialize the allocated memory.

Sort of. In that same sense, malloc also does not not initialize the allocated memory.

Moreover, that malloc did not actively initialize the allocated memory would in no way ensure that you would see any nonzero contents. You could get all-zeroes in some allocations for reasons that have nothing to do with the implementation of malloc().

However, on macOS arm64, all values appear as zero. Why does this phenomenon occur?

C does not require such behavior. It does not speak to why you observe it.

There are a number of possible reasons outside of C. My first guess would be that your machine's virtual memory subsystem provides zero-initialized memory to the program, such that when malloc allocates memory that the program has not used before, it contains all zeroes because it came that way from the OS.

There are other possibilities. Most of them have the characteristic that even though you see zero-initialized memory from some malloc calls, there are circumstances under which malloc would provide memory that is not all-zero.

Is this related to ASLR?

Unlikely.

Comments

3

malloc does not initialize the allocated memory.

This does not is amiss. There is no specification to not initialize.
An implementation of malloc() may initialize that memory, it may not.
It may initialize sometimes (like the first time), sometimes not.
What malloc() must meet is the specification:

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

indeterminate representation: object representation that either represents an unspecified value or is a non-value representation

unspecified value: valid value of the relevant type where this document imposes no requirements on which value is chosen in any instance


"malloc does not certainly initialize the allocated memory" is a better conclusion.

Comments

1

Firstly, use void as your main()'s formal argument.

Secondly, this phenomenon can be witnessed on UNIX and its derivatives including MacOS and GNU/Linux. For security reasons the OS would wipe all the bytes to 0. Albeit malloc() wouldn't clear the garbage data for you unlike calloc(); It keeps the previous process' garbage data intact. But when the OS exits the previous process it does clear previous process' garbage.

2 Comments

"It keeps the previous process' garbage data intact." is not certain. malloc() may or may do that - sometimes. It is not specified by C. "when the OS exits the previous process it does clear previous process' garbage." --> this is not certain either. The OS may or may not do this. It is also not specified by C.
In your answer, you wrote: "It keeps the previous process' garbage data intact" -- This statement is incorrect for most modern UNIX-based operating systems. A process will generally never see the any garbage data from another process, even when using malloc instead of calloc, because for security reasons, most operating systems will zero all memory before passing it to another process. This happens irrespective of whether the previous process has exited or not.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.