Maximum memory which malloc can allocate

CMemory ManagementOperating SystemMallocCpu Architecture

C Problem Overview


I was trying to figure out how much memory I can malloc to maximum extent on my machine (1 Gb RAM 160 Gb HD Windows platform).

I read that the maximum memory malloc can allocate is limited to physical memory (on heap).

Also when a program exceeds consumption of memory to a certain level, the computer stops working because other applications do not get enough memory that they require.

So to confirm, I wrote a small program in C:

int main(){  
    int *p;
    while(1){
        p=(int *)malloc(4);
        if(!p)break;
    }	
}

I was hoping that there would be a time when memory allocation would fail and the loop would break, but my computer hung as it was an infinite loop.

I waited for about an hour and finally I had to force shut down my computer.

Some questions:

  • Does malloc allocate memory from HD also?
  • What was the reason for above behaviour?
  • Why didn't loop break at any point of time?
  • Why wasn't there any allocation failure?

C Solutions


Solution 1 - C

> I read that the maximum memory malloc can allocate is limited to physical memory (on heap).

Wrong: most computers/OSs support virtual memory, backed by disk space.

> Some questions: does malloc allocate memory from HDD also?

malloc asks the OS, which in turn may well use some disk space.

> What was the reason for above behavior? Why didn't the loop break at any time? > > Why wasn't there any allocation failure?

You just asked for too little at a time: the loop would have broken eventually (well after your machine slowed to a crawl due to the large excess of virtual vs physical memory and the consequent super-frequent disk access, an issue known as "thrashing") but it exhausted your patience well before then. Try getting e.g. a megabyte at a time instead.

> When a program exceeds consumption of memory to a certain level, the > computer stops working because other applications do not get enough > memory that they require.

A total stop is unlikely, but when an operation that normally would take a few microseconds ends up taking (e.g.) tens of milliseconds, those four orders of magnitude may certainly make it feel as if the computer had basically stopped, and what would normally take a minute could take a week.

Solution 2 - C

I know this thread is old, but for anyone willing to give it a try oneself, use this code snipped

#include <stdlib.h>

int main() {
int *p;
while(1) {
	int inc=1024*1024*sizeof(char);
	p=(int*) calloc(1,inc);
	if(!p) break;
	}
}

run

$ gcc memtest.c
$ ./a.out

upon running, this code fills up ones RAM until killed by the kernel. Using calloc instead of malloc to prevent "lazy evaluation". Ideas taken from this thread: https://stackoverflow.com/questions/4383059/malloc-memory-questions

This code quickly filled my RAM (4Gb) and then in about 2 minutes my 20Gb swap partition before it died. 64bit Linux of course.

Solution 3 - C

/proc/sys/vm/overcommit_memory controls the maximum on Linux

On Ubuntu 19.04 for example, we can easily see that malloc is implemented with mmap(MAP_ANONYMOUS by using strace.

Then man proc then describes how /proc/sys/vm/overcommit_memory controls the maximum allocation:

> This file contains the kernel virtual memory accounting mode. Values are: > > - 0: heuristic overcommit (this is the default) > - 1: always overcommit, never check > - 2: always check, never overcommit > > In mode 0, calls of mmap(2) with MAP_NORESERVE are not checked, and the default check is very weak, leading to the risk of getting a process "OOM-killed". > > In mode 1, the kernel pretends there is always enough memory, until memory actually runs out. One use case for this mode is scientific computing applications that em‐ ploy large sparse arrays. In Linux kernel versions before 2.6.0, any nonzero value implies mode 1. > > In mode 2 (available since Linux 2.6), the total virtual address space that can be allocated (CommitLimit in /proc/meminfo) is calculated as > > CommitLimit = (total_RAM - total_huge_TLB) * overcommit_ratio / 100 + total_swap > > where: > > - total_RAM is the total amount of RAM on the system; > - total_huge_TLB is the amount of memory set aside for huge pages; > - overcommit_ratio is the value in /proc/sys/vm/overcommit_ratio; and > - total_swap is the amount of swap space. > > For example, on a system with 16GB of physical RAM, 16GB of swap, no space dedicated to huge pages, and an overcommit_ratio of 50, this formula yields a Com‐ mitLimit of 24GB. > > Since Linux 3.14, if the value in /proc/sys/vm/overcommit_kbytes is nonzero, then CommitLimit is instead calculated as: > > CommitLimit = overcommit_kbytes + total_swap > > See also the description of /proc/sys/vm/admiin_reserve_kbytes and /proc/sys/vm/user_reserve_kbytes.

Documentation/vm/overcommit-accounting.rst in the 5.2.1 kernel tree also gives some information, although lol a bit less:

> The Linux kernel supports the following overcommit handling modes > > - 0 Heuristic overcommit handling. Obvious overcommits of address > space are refused. Used for a typical system. It ensures a > seriously wild allocation fails while allowing overcommit to > reduce swap usage. root is allowed to allocate slightly more > memory in this mode. This is the default. > > - 1 Always overcommit. Appropriate for some scientific > applications. Classic example is code using sparse arrays and > just relying on the virtual memory consisting almost entirely > of zero pages. > > - 2 Don't overcommit. The total address space commit for the > system is not permitted to exceed swap + a configurable amount > (default is 50%) of physical RAM. Depending on the amount you > use, in most situations this means a process will not be > killed while accessing pages but will receive errors on memory > allocation as appropriate. > > Useful for applications that want to guarantee their memory > allocations will be available in the future without having to > initialize every page.

Minimal experiment

We can easily see the maximum allowed value with:

main.c

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char **argv) {
    char *chars;
    size_t nbytes;

    /* Decide how many ints to allocate. */
    if (argc < 2) {
        nbytes = 2;
    } else {
        nbytes = strtoull(argv[1], NULL, 0);
    }

    /* Allocate the bytes. */
    chars = mmap(
        NULL,
        nbytes,
        PROT_READ | PROT_WRITE,
        MAP_SHARED | MAP_ANONYMOUS,
        -1,
        0
    );

    /* This can happen for example if we ask for too much memory. */
    if (chars == MAP_FAILED) {
        perror("mmap");
        exit(EXIT_FAILURE);
    }

    /* Free the allocated memory. */
    munmap(chars, nbytes);

    return EXIT_SUCCESS;
}

GitHub upstream.

Compile and run to allocate 1GiB and 1TiB:

gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out 0x40000000
./main.out 0x10000000000

We can then play around with the allocation value to see what the system allows.

I can't find a precise documentation for 0 (the default), but on my 32GiB RAM machine it does not allow the 1TiB allocation:

mmap: Cannot allocate memory

If I enable unlimited overcommit however:

echo 1 | sudo tee /proc/sys/vm/overcommit_memory

then the 1TiB allocation works fine.

Mode 2 is well documented, but I'm lazy to carry out precise calculations to verify it. But I will just point out that in practice we are allowed to allocate about:

overcommit_ratio / 100

of total RAM, and overcommit_ratio is 50 by default, so we can allocate about half of total RAM.

VSZ vs RSS and the out-of-memory killer

So far, we have just allocated virtual memory.

However, at some point of course, if you use enough of those pages, Linux will have to start killing some processes.

I have illustrated that in detail at: https://stackoverflow.com/questions/7880784/what-is-rss-and-vsz-in-linux-memory-management/57453334#57453334

Solution 4 - C

Try this

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

main() {
    int Mb = 0;
    while (malloc(1<<20)) ++Mb;
    printf("Allocated %d Mb total\n", Mb);
}

Include stdlib and stdio for it.
This extract is taken from deep c secrets.

Solution 5 - C

malloc does its own memory management, managing small memory blocks itself, but ultimately it uses the Win32 Heap functions to allocate memory. You can think of malloc as a "memory reseller".

The windows memory subsystem comprises physical memory (RAM) and virtual memory (HD). When physical memory becomes scarce, some of the pages can be copied from physical memory to virtual memory on the hard drive. Windows does this transparently.

By default, Virtual Memory is enabled and will consume the available space on the HD. So, your test will continue running until it has either allocated the full amount of virtual memory for the process (2GB on 32-bit windows) or filled the hard disk.

Solution 6 - C

As per C90 standard guarantees that you can get at least one object 32 kBytes in size, and this may be static, dynamic, or automatic memory. C99 guarantees at least 64 kBytes. For any higher limit, refer your compiler's documentation.

Also, malloc's argument is a size_t and the range of that type is [0,SIZE_MAX], so the maximum you can request is SIZE_MAX, which value varies upon implementation and is defined in <limits.h>.

Solution 7 - C

I don't actually know why that failed, but one thing to note is that `malloc(4)" may not actually give you 4 bytes, so this technique is not really an accurate way to find your maximum heap size.

I found this out from my question here.

For instance, when you declare 4 bytes of memory, the space directly before your memory could contain the integer 4, as an indication to the kernel of how much memory you asked for.

Solution 8 - C

when first time you allocate any size to *p, every next time you leave that memory to be unreferenced. That means

> at a time your program is allocating memory of 4 bytes only

. then how can you thing you have used entire RAM, that's why SWAP device( temporary space on HDD) is out of discussion. I know an memory management algorithm in which when no one program is referencing to memory block, that block is eligible to allocate for programs memory request. That's why you are just keeping busy to RAM Driver and that's why it can't give chance to service other programs. Also this a dangling reference problem.

Ans : You can at most allocate the memory of your RAM size. Because no program has access to swap device.

I hope your all questions has got satisfactory answers.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionVikasView Question on Stackoverflow
Solution 1 - CAlex MartelliView Answer on Stackoverflow
Solution 2 - CSebastianView Answer on Stackoverflow
Solution 3 - CCiro Santilli Путлер Капут 六四事View Answer on Stackoverflow
Solution 4 - Chuman.jsView Answer on Stackoverflow
Solution 5 - CmdmaView Answer on Stackoverflow
Solution 6 - Cmav_2kView Answer on Stackoverflow
Solution 7 - CChris CooperView Answer on Stackoverflow
Solution 8 - CSwapnilView Answer on Stackoverflow