68

What is the difference between xmalloc() and malloc() for memory allocation?
Is there any pro of using xmalloc()?

apaderno
  • 28,547
  • 16
  • 75
  • 90
vaichidrewar
  • 9,251
  • 18
  • 72
  • 86

6 Answers6

88

xmalloc() is a non-standard function that has the motto succeed or die. If it fails to allocate memory, it will terminate your program and print an error message to stderr.

The allocation itself is no different; only the behaviour in the case that no memory could be allocated is different.

Use malloc(), since it's more friendly and standard.

apaderno
  • 28,547
  • 16
  • 75
  • 90
orlp
  • 112,504
  • 36
  • 218
  • 315
  • 1
    Learned something new. Thanks! I'd just explain `xmalloc` and leave it at that. Or perhaps say, _use whatever makes sense to your situation_. For instance if I'm writing a program for a specific OS and it's not mission-critical that I don't mind losing data in OOM, `xmalloc` makes sense. – legends2k Dec 27 '21 at 09:38
29

xmalloc is not part of the standard library. It's usually the name of a very harmful function for lazy programmers that's common in lots of GNU software, which calls abort if malloc fails. Depending on the program/library, it might also convert malloc(0) into malloc(1) to ensure that xmalloc(0) returns a unique pointer.

In any case, aborting on malloc failure is very very bad behavior, especially for library code. One of the most infamous examples is GMP (the GNU multiprecision arithmetic library), which aborts the calling program whenever it runs out of memory for a computation.

Correct library-level code should always handle allocation failures by backing out whatever partially-completed operation it was in the middle of and returning an error code to the caller. The calling program can then decide what to do, which will likely involve saving critical data.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 8
    Of course, `saving critical data` and pretty much anything else which the calling program may want to do also requires allocating memory pages (even if you don't actually do allocate yourself, library functions need to do so). I don't think it's very likely that you can recover in any case. – Frerich Raabe May 19 '14 at 09:20
  • 6
    If it does then you're doing it wrong. There's no legitimate need for serialization to use any new allocations. – R.. GitHub STOP HELPING ICE May 19 '14 at 11:37
  • 44
    Calling developers that use `xmalloc()` 'lazy programmers' is unfair. Detecting allocation errors is [not always possible](http://www.win.tue.nl/~aeb/linux/lk/lk-9.html#ss9.6). Isn't it a waste of time and money to bloat your code base with checks on the return value of `malloc()` if your target OS is one where `malloc()` (essentially) _never fails_ due to overcommit being enabled? Coding an in-house level editor for a game as though it were an air traffic control system just drives up the cost with no real benefit. Outside of safety-critical systems, it's okay to be 'lazy' sometimes, IMHO. – evadeflow Jun 13 '14 at 22:41
  • 12
    @evadeflow: Tell that to the person who loses their document due to accidentally opening a second document that's too large to fit in memory (happened just yesterday to someone who doesn't believe me on this issue). – R.. GitHub STOP HELPING ICE Jun 13 '14 at 23:23
  • 6
    I agree that not having a strategy to prevent data loss qualifies as 'lazy'. But many applications unapologetically terminate (https://developer.gnome.org/glib/2.28/glib-Memory-Allocation.html#glib-Memory-Allocation.description) when `malloc()` fails and still manage not to lose data because they (for example) embed SQLite and journal all operations. Granted, SQLite has quite robust (and [well-tested](http://www.sqlite.org/testing.html#oomtesting)) OOM detection, so it plays to your point that this _is_ an important problem. I'd just rather let someone else solve it. Does that make me lazy? – evadeflow Jun 16 '14 at 16:57
  • 11
    @evadeflow: That's a valid approach at the application level, but not at the library level. It's not reasonable for a library (e.g. glib) to assume the calling application does not have any non-journaled data it doesn't care about losing. And if a library is going to behave this way, it should document that requirement prominently rather than hiding it in the documentation for the allocation functions. Of course they won't do that, because nobody would knowingly use a library documented as such; to get people to use such a low-quality library you have to hide the issue. – R.. GitHub STOP HELPING ICE Jun 16 '14 at 17:04
  • 6
    -pedantic: GCC 5.2 calls `exit`, not `abort`: http://stackoverflow.com/a/31556623/895245 which will run `atexit` and the GNU `xatexit` callbacks. – Ciro Santilli OurBigBook.com Jul 22 '15 at 07:39
  • 3
    Just as a note (not saying it's right or wrong), some other languages panic or abort as a matter of course (i.e. Rust's standard library) under OOM conditions (and that's if the OS itself doesn't kill the application before that). – Learn OpenGL ES Mar 29 '18 at 23:32
  • 2
    I do think that there are plenty of simple command line tools that wouldn't really do any harm by using this function. As long as there's no external state that could be left incomplete (e.g. the rename command only renaming half of your files), I don't see the harm in killing the process if the system runs out of memory. What benefit would there be to recovering from a failed allocation in the command "ls"? I think that a partially printed directory listing and a "Ran out of memory; aborting" message is perfectly acceptable, and would safely reduce the size of the codebase. – John Leuenhagen Oct 22 '21 at 01:43
  • Most (or all?) GNU projects are volunteer contributions to the community. Calling them _lazy_ makes little sense IMHO. Perhaps other volunteers can jump in and fix such issues in those projects as they're open to contributions. Tagging a group of programmers is just unproducitve. – legends2k Dec 27 '21 at 09:31
  • 1
    @legends2k: I wrote this answer 10 years ago and would probably write it somewhat differently now. – R.. GitHub STOP HELPING ICE Dec 27 '21 at 15:10
26

As others have mentioned, it's true that xmalloc is very often implemented as a wrapper function that invokes the OS-supplied malloc and blindly calls abort or exit if it fails. However, many projects contain an xmalloc function that tries to save application state before exiting (see, for example, neovim).

Personally, I think of xmalloc as a kind of project-specific extended malloc rather than an exiting malloc. Though I don't recall ever seeing a version that didn't wind up calling abort or exit, some of them do a lot more than that.

So the answer to the question "What's the difference between xmalloc and malloc is: it depends. xmalloc is a non-standard, project-specific function, so it could do anything at all. The only way to know for sure is to read the code.

Patrick Ziegler
  • 787
  • 1
  • 7
  • 20
evadeflow
  • 4,704
  • 38
  • 51
9

xmalloc is part of libiberty

https://gcc.gnu.org/onlinedocs/libiberty/index.html which is a GNU utils library.

malloc is ANSI C.

xmalloc is often included in-source in many important GNU projects, including GCC and Binutils, both of which use it a lot. But it is also possible to build it as a dynamic library to use in your programs. E.g. Ubuntu has the libiberty-dev package.

xmalloc is documented at: https://gcc.gnu.org/onlinedocs/libiberty/Functions.html and on GCC 5.2.0 it is implemented on libiberty/xmalloc.c

PTR
xmalloc (size_t size)
{
  PTR newmem;

  if (size == 0)
    size = 1;
  newmem = malloc (size);
  if (!newmem)
    xmalloc_failed (size);

  return (newmem);
}

void
xmalloc_failed (size_t size)
{
#ifdef HAVE_SBRK
  extern char **environ;
  size_t allocated;

  if (first_break != NULL)
    allocated = (char *) sbrk (0) - first_break;
  else
    allocated = (char *) sbrk (0) - (char *) &environ;
  fprintf (stderr,
       "\n%s%sout of memory allocating %lu bytes after a total of %lu bytes\n",
       name, *name ? ": " : "",
       (unsigned long) size, (unsigned long) allocated);
#else /* HAVE_SBRK */
  fprintf (stderr,
       "\n%s%sout of memory allocating %lu bytes\n",
       name, *name ? ": " : "",
       (unsigned long) size);
#endif /* HAVE_SBRK */
  xexit (1);
}

/* This variable is set by xatexit if it is called.  This way, xmalloc
   doesn't drag xatexit into the link.  */
void (*_xexit_cleanup) (void);

void
xexit (int code)
{
  if (_xexit_cleanup != NULL)
    (*_xexit_cleanup) ();
  exit (code);
}

Which as others mentioned, is pretty straightforward:

  • try malloc
  • if it fails
    • print error messages
    • call exit
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
  • why the f are they not using __builtin_expect here? with that code, it will do an extra jmp every time it succeeds... it should be the other way around (do an extra jmp every time it fails) – hanshenrik May 12 '18 at 08:48
  • @hanshenrik if you benchmark it and notice a difference, describe me the setup and I'll mention at: https://stackoverflow.com/questions/7346929/what-is-the-advantage-of-gccs-builtin-expect-in-if-else-statements/31540623#31540623 :-) – Ciro Santilli OurBigBook.com May 12 '18 at 09:13
  • 1
    unfortunately, benchmarking it is difficult because of the size of the branch predictor of modern CPUs. to see a difference, you'll probably need to do so much in between each invocation of xmalloc that the branch predictor has forgotten which branch was taken the last time.. =/ – hanshenrik May 12 '18 at 09:25
  • @hanshenrik I know :-) And then it won't be measurable most likely. – Ciro Santilli OurBigBook.com May 12 '18 at 09:27
8

an primitive example of xmalloc.c in K&R C

#include <stdio.h>
extern char *malloc ();
void *
xmalloc (size)
    unsigned size;
{
  void *new_mem = (void *) malloc (size);
  if (new_mem == NULL)    
    {
      fprintf (stderr, "fatal: memory exhausted (xmalloc of %u bytes).\n", size);
      exit (-1);
    }
  return new_mem;
}

then in your code header (early) you put

#define malloc(m) xmalloc(m)

to silently rewrite the source before compilation. (you can see the rewritten code by invoking the C preprocessor directly and saving the output. )

if crashing your program is not what you want you can do something different

  • Use a garbage collector
  • redesign your code to be less of a memory hog
  • have error checking code in your program to handle an Out of Memory or other allocation error gracefully.

Users don't enjoy losing their data to a built-in crash command in their program.

spikeysnack
  • 81
  • 1
  • 1
  • 1
    @MilesRout: it's K&R C - very old stuff. – orlp Feb 04 '13 at 20:25
  • +1, but garbage collection and C probably [don't go very well together.](http://stackoverflow.com/q/41113029/1275653) – thb Dec 13 '16 at 14:17
  • 2
    @thb In specialized applications it could be nice. Sure, it won't work for everything but there are things where it works nicely. ALSO... Well, garbage collection in a language's runtime is garbage collection in C as the runtime itself is written in C. – Paul Stelian Apr 03 '19 at 16:29
2

I have seen xmalloc while working on IBM AIX. xmalloc is a kernel service provided by AIX.

Nothing can explain a function better than the function's man page in my opinion. So I am pasting the below details from the man page

Purpose: Allocates memory.

Syntax:

caddr_t xmalloc ( size, align, heap)

Parameters:

size: Specifies the number of bytes to allocate.

align: Specifies the alignment characteristics for the allocated memory.

heap : Specifies the address of the heap from which the memory is to be allocated.

Description:

The xmalloc kernel service allocates an area of memory out of the heap specified by the heap parameter. This area is the number of bytes in length specified by the size parameter and is aligned on the byte boundary specified by the align parameter. The align parameter is actually the log base 2 of the desired address boundary. For example, an align value of 4 requests that the allocated area be aligned on a 2^4 (16) byte boundary.

There are multiple heaps provided by the kernel for use by kernel extensions. Two primary kernel heaps are kernel_heap and pinned_heap. Kernel extensions should use the kernel_heap value when allocating memory that is not pinned, and should use the pinned_heap value when allocating memory that should always be pinned or pinned for long periods of time. When allocating from the pinned_heap heap, the xmalloc kernel service will pin the memory before a successful return. The pin and unpin kernel services should be used to pin and unpin memory from the kernel_heap heap when the memory should only be pinned for a limited amount of time. Memory from the kernel_heap heap must be unpinned before freeing it. Memory from the pinned_heap heap should not be unpinned.

If one is interested in knowing more about this function can visit the following link: IBM AIX Support

MaxPowers
  • 5,235
  • 2
  • 44
  • 69
Albert
  • 415
  • 5
  • 15