Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to lazy allocate zeroed memory?

From what I understand, I have to choose between calloc, which will allocate zeroed memory, and malloc, which can allocate memory on demand.

Is there a function that combines both those properties? Maybe direct call to mmap?

If it's possible, why calloc doesn't do it?

like image 935
Piotr Praszmo Avatar asked Dec 27 '22 11:12

Piotr Praszmo


2 Answers

There are a few mechanisms to get pre-zeroed memory from the operating system:

mmap(2)'s MAP_ANONYMOUS flag forces the contents to be initialized to zero.

The POSIX shared memory segments can also zero

  • shm_open(3) provides you with a file descriptor
  • ftruncate(2) the "file" to the size you want
  • mmap(2) the "file" into your address space

The memory comes pre-zeroed:

   This volume of IEEE Std 1003.1-2001 specifies that memory
   objects have initial contents of zero when created. This is
   consistent with current behavior for both files and newly
   allocated memory. For those implementations that use physical
   memory, it would be possible that such implementations could
   simply use available memory and give it to the process
   uninitialized. This, however, is not consistent with standard
   behavior for the uninitialized data area, the stack, and of
   course, files. Finally, it is highly desirable to set the
   allocated memory to zero for security reasons. Thus,
   initializing memory objects to zero is required.

It appears that this memory is zeroed at use: mm/shmem.c function shmem_zero_setup():

/**
 * shmem_zero_setup - setup a shared anonymous mapping
 * @vma: the vma to be mmapped is prepared by do_mmap_pgoff
 */     
int shmem_zero_setup(struct vm_area_struct *vma)
{   
    struct file *file;
    loff_t size = vma->vm_end - vma->vm_start;

    file = shmem_file_setup("dev/zero", size, vma->vm_flags);
    if (IS_ERR(file))
        return PTR_ERR(file);

    if (vma->vm_file)
        fput(vma->vm_file);
    vma->vm_file = file;
    vma->vm_ops = &shmem_vm_ops;
    return 0;
}
like image 84
sarnold Avatar answered Jan 09 '23 10:01

sarnold


If you're trying to emulate calloc with malloc (i.e. Use malloc but receive zeroed memory) then you can do so with memset:

foo = (char*)malloc(BLOCK_SIZE);
memset(foo,'\0',BLOCK_SIZE);

However, this is a bad idea (It's slower than calloc, see: Why malloc+memset is slower than calloc? ) and does not result in the 'lazy allocation' you refer to due to the reasons stated in Fritschy's answer.

like image 44
Andrew Stubbs Avatar answered Jan 09 '23 10:01

Andrew Stubbs