There are a lot of questions about memory allocation on this site, but I couldn't find one that specifically addresses my concern. This question seems closest, and it led me to this article, so... I compared the behavior of the three demo programs it contains on a (virtual) desktop x86 Linux system and an ARM-based system.
My findings are detailed here, but
the quick summary is: on my desktop system, the demo3
program from the
article seems to show that malloc()
always lies about the amount of memory
allocated—even with swap disabled. For example, it cheerfully 'allocates' 3
GB of RAM, and then invokes the OOM killer when the program starts to actually
write to all that memory. With swap disabled, the OOM killer gets invoked
after writing to only 610 MB of the 3 GB malloc()
has supposedly made
available.
The purpose of the demo program is to demonstrate this well-documented 'feature' of Linux, so none of this is too surprising.
But the behavior is different on our i.MX6-based embedded target at work,
where malloc()
appears to be telling the truth about how much RAM it
allocates(?) The program below (reproduced verbatim from the article) always
gets OOM-killed in the second loop when i == n
:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 10000
int main (void) {
int i, n = 0;
char *pp[N];
for (n = 0; n < N; n++) {
pp[n] = malloc(1<<20);
if (pp[n] == NULL)
break;
}
printf("malloc failure after %d MiB\n", n);
for (i = 0; i < n; i++) {
memset (pp[i], 0, (1<<20));
printf("%d\n", i+1);
}
return 0;
}
So my question, in a nutshell, is: why does the demo3
program—or some other
unlucky OOM killer victim—always get killed long before i == n
on my
desktop system (implying that malloc()
is a liar), but it only gets killed
when i == n
on our i.MX6 ARM target (implying that malloc()
may be telling the
truth)? Is this difference a function of the libc and/or kernel version, or
something else? Can I conclude that malloc()
will always return NULL if
allocation fails on this target?
NOTE: Some details on each system (please note that overcommit_memory
and overcommit_ratio
have the same values for both):
# Desktop system
% uname -a
Linux ubuntu 3.8.0-33-generic #48-Ubuntu SMP Wed Oct 23 17:26:34 UTC 2013 i686 i686 i686 GNU/Linux
% /lib/i386-linux-gnu/libc.so.6
GNU C Library (Ubuntu EGLIBC 2.17-0ubuntu5.1) stable release version 2.17, by Roland McGrath et al.
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.7.3.
Compiled on a Linux 3.8.13 system on 2013-09-30.
Available extensions:
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/eglibc/+bugs>.
% cat /proc/sys/vm/overcommit_memory
0
% cat /proc/sys/vm/overcommit_ratio
50
# i.MX6 ARM system
# uname -a
Linux acmewidgets 3.0.35-ts-armv7l #2 SMP PREEMPT Mon Aug 12 19:27:25 CST 2013 armv7l GNU/Linux
# /lib/libc.so.6
GNU C Library (GNU libc) stable release version 2.17, by Roland McGrath et al.
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.7.3.
Compiled on a Linux 3.0.35 system on 2013-08-14.
Available extensions:
crypt add-on version 2.1 by Michael Glad and others
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
libc ABIs: UNIQUE
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.
# cat /proc/sys/vm/overcommit_memory
0
% cat /proc/sys/vm/overcommit_ratio
50
BACKGROUND: We're trying to decide how to handle low memory conditions in our
media-oriented embedded application, and want to know whether we can—for this specific target—trust malloc()
to alert us when allocation fails. My experience with desktop Linux
apps made me think the answer was certainly not, but now I'm not so sure.