Re: More than 2, but less than 3 GiB per process memory?
Am Montag, 26. September 2005 20:29 schrieb Hendrik Boom:
> On Mon, Sep 26, 2005 at 11:34:15AM -0600, Bob Proulx wrote:
> > Hendrik Boom wrote:
> > > > Malte Cornils wrote:
> > > > > Does anyone have a clue why 2 GiB is the limit?
> > It is not for me. I can malloc() up to 2.9G.
> I've heard that the kernel allocates memory "optimistically".
> That is, when it allocates it it only allocates address space.
> It commits real storage (whether RAM or swap space) to the allocated
> storage only when the storage is actually used.
> Could it be that just mallocing the storage is not enough for it to count
> as being "used?" Would you need actually to write something in each page?
Indeed, I get up to 3058 M; that on a system with 8 GiB swap and on a system
with 512 MB RAM and 1 GiB swap. At least on the latter, this has to be
overcommitting since that much virtual memory is definitely not available.
From the malloc(3) man page:
> By default, Linux follows an optimistic memory allocation strategy.
> This means that when malloc() returns non-NULL there is no guarantee
> that the memory really is available. This is a really bad bug. In case
> it turns out that the system is out of memory, one or more processes
> will be killed by the infamous OOM killer. In case Linux is employed
> under circumstances where it would be less desirable to suddenly lose
> some randomly picked processes, and moreover the kernel version is suf-
> ficiently recent, one can switch off this overcommitting behavior using
> a command like
> # echo 2 > /proc/sys/vm/overcommit_memory
> See also the kernel Documentation directory, files vm/overcommit-
> accounting and sysctl/vm.txt.
There is a /proc/sys/vm/overcommit_memory file, but no matter whether I put
"2", "1" or "0" in there, the behaviour of your test program does not change
My 2 GiB limit could be caused by using the brk() system call in the malloc
implementation: The brk() system call uses a signed 32bit integer for the
size, and this obviously cannot go above 2 Gig. Which might explain why my
test program fails when allocating that much memory at once.
However, glibc's malloc documentation says that it uses the brk system call
for smaller amounts of memory only and mmap for larger amounts. Hmm. Lots of
questions, few answers :-)
From glibc-2.3.2's source code (malloc/malloc.c, line 129ff):
> Maximum allocated size: 4-byte size_t: 2^32 minus about two pages
> 8-byte size_t: 2^64 minus about two pages
> It is assumed that (possibly signed) size_t values suffice to
> represent chunk sizes. `Possibly signed' is due to the fact
> that `size_t' may be defined on a system as either a signed or
> an unsigned type. The ISO C standard says that it must be
> unsigned, but a few systems are known not to adhere to this.
> Additionally, even when size_t is unsigned, sbrk (which is by
> default used to obtain memory from system) accepts signed
> arguments, and may not be able to handle size_t-wide arguments
> with negative sign bit. Generally, values that would
> appear as negative after accounting for overhead and alignment
> are supported only via mmap(), which does not have this
There is also the question whether the limits (set with the ulimit command)
have an influence here, from setrmlimit man page:
> The maximum size of the process's virtual memory (address space)
> in bytes. This limit affects calls to brk(2), mmap(2) and
> mremap(2), which fail with the error ENOMEM upon exceeding this
> limit. Also automatic stack expansion will fail (and generate a
> SIGSEGV that kills the process if no alternate stack has been
> made available via sigaltstack(2)). Since the value is a long,
> on machines with a 32-bit long either this limit is at most 2
> GiB, or this resource is unlimited.
However, ulimit -a says the limits important for memory allocation are set to
unlimited on my systems.