Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the memory chunk returned by malloc (and its cousins) initialized to Zero?

I wrote a code to test to stress test the memory management of Linux and Windows OS. Just for further tests I went ahead and checked what values are present in the memory returned by malloc().

The values that are being return are all 0 (zero). I have read the man page of malloc, checked on both Windows and Linux, but I am not able to find the reason for this behavior. According to the manpage the

The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized.

To clear the memory segment, one has to manually use memset().

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

int eat(long total,int chunk){
    long i;
    for(i=0;i<total;i+=chunk){
        short *buffer=malloc(sizeof(char)*chunk);     
        if(buffer==NULL){
            return -1;
        }
        printf("\nDATA=%d",*buffer);
        memset(buffer,0,chunk);
    }
    return 0;
}

int main(int argc, char *argv[]){
    int i,chunk=1024;
    long size=10000;
            printf("Got %ld bytes in chunks of %d...\n",size,chunk);
            if(eat(size,chunk)==0){
                printf("Done, press any key to free the memory\n");
                getchar();
            }else{
                printf("ERROR: Could not allocate the memory");
            }
        }

Maybe I am missing something. The code is adapted from here

EDIT: The problem has been been answered here for the GCC specific output. I believe Windows operating system would be also following the same procedures.

like image 379
coder Avatar asked Mar 05 '15 15:03

coder


People also ask

Which of the following will initialize the new memory to 0?

Memory Allocation With calloc calloc returns a pointer to the first element of the allocated elements. If memory cannot be allocated, calloc returns NULL . If the allocation is successful, calloc initializes all bits to 0.

How the memory chunks are allocated?

Dynamic memory allocation involves 2 central commands: malloc allocates a portion of unused memory for use by a process, while free frees a previously-allocated portion of memory, allowing it to be reused.

Does malloc returns an address?

The function MALLOC() allocates an area of memory and returns the address of the start of that area. The argument to the function is an integer specifying the amount of memory to be allocated, in bytes. If successful, it returns a pointer to the first item of the region; otherwise, it returns an integer 0.

What is chunk size in malloc?

The maximum size chunk is 2^31 - 8 bytes. malloc(0) returns a pointer to something of the minimum allocatable size. Requests for negative sizes (when size_t is signed) or those greater than (2^31 - 8) bytes will also return a minimum-sized chunk.


2 Answers

The memory returned by malloc() is not initialized, which means it may be anything. It may be zero, and it may not be; 'not initialized' means it could be anything (zero included). To get a guaranteed zeroed page use calloc().

The reason you are seeing zeroed pages (on Linux anyway) is that if an application requests new pages, these pages are zeroed by the OS (or more precisely they are copy-on-write images of a fixed page of zeroes known as the 'global zero page'). But if malloc() happens to use memory already allocated to the application which has since been freed (rather than expanding the heap) you may well see non-zero data. Note the zeroing of pages provided by the OS is an OS specific trait (primarily there for security so that one process doesn't end up with pages that happen to have data from another process), and is not mandated by the C standard.

You asked for a source for get_free_page zeroing the page: that says 'get_free_page() takes one parameter, a priority. ... It takes a page off of the free_page_list, updates mem_map, zeroes the page and returns the physical address of the page.' Here's another post that explains it well, and also explains why using calloc() is better than malloc()+memset().

Note that you aren't checking the entire allocated chunk for zero. You want something like this (untested):

int n;
char nonzero=0;
char *buffer=malloc(sizeof(char)*chunk);     
if(buffer==NULL){
    return -1;
}
for (n = 0; n<chunk; n++)
    nonzero = nonzero || buffer[n];  
printf("\nDATA=%s\n",nonzero?"nonzero":"zero");
like image 110
abligh Avatar answered Oct 05 '22 17:10

abligh


You're absolutely correct; this behaviour is not guaranteed by the C language standard.

What you're observing could just be chance (you're only checking a couple of bytes in each allocation), or it could be an artifact of how your OS and C runtime library are allocating memory.

like image 36
Oliver Charlesworth Avatar answered Oct 05 '22 18:10

Oliver Charlesworth