diff --git a/src/dir_common.c b/src/dir_common.c
index ee80c81da161bfde522f12e65d3ceb35a46f36d2..3a2a9d0fd54127274a3c76ef07fb64fad85f1b9e 100644
--- a/src/dir_common.c
+++ b/src/dir_common.c
@@ -44,7 +44,7 @@ static int lasterrl; /* ^ of lasterr */
 static void curpath_resize(int s) {
   if(curpathl < s) {
     curpathl = s < 128 ? 128 : s < curpathl*2 ? curpathl*2 : s;
-    dir_curpath = realloc(dir_curpath, curpathl);
+    dir_curpath = xrealloc(dir_curpath, curpathl);
   }
 }
 
@@ -85,7 +85,7 @@ void dir_setlasterr(const char *path) {
   int req = strlen(path)+1;
   if(lasterrl < req) {
     lasterrl = req;
-    lasterr = realloc(lasterr, lasterrl);
+    lasterr = xrealloc(lasterr, lasterrl);
   }
   strcpy(lasterr, path);
 }
@@ -99,7 +99,7 @@ void dir_seterr(const char *fmt, ...) {
 
   va_list va;
   va_start(va, fmt);
-  dir_fatalerr = malloc(1024); /* Should be enough for everything... */
+  dir_fatalerr = xmalloc(1024); /* Should be enough for everything... */
   vsnprintf(dir_fatalerr, 1023, fmt, va);
   dir_fatalerr[1023] = 0;
   va_end(va);
diff --git a/src/dir_import.c b/src/dir_import.c
index 13ebe644e30d0c79aee46f9ebf0d620da3825ccb..01b987d376de3d530f68c835f528f93b17e70ce6 100644
--- a/src/dir_import.c
+++ b/src/dir_import.c
@@ -596,12 +596,12 @@ int dir_import_init(const char *fn) {
   else if((stream = fopen(fn, "r")) == NULL)
     return 1;
 
-  ctx = malloc(sizeof(struct ctx));
+  ctx = xmalloc(sizeof(struct ctx));
   ctx->stream = stream;
   ctx->line = 1;
   ctx->byte = ctx->eof = ctx->items = 0;
   ctx->buf = ctx->lastfill = ctx->readbuf;
-  ctx->buf_dir = malloc(dir_memsize(""));
+  ctx->buf_dir = xmalloc(dir_memsize(""));
   ctx->readbuf[0] = 0;
 
   dir_curpath_set(fn);
diff --git a/src/dir_mem.c b/src/dir_mem.c
index f1a074208a8f637b24408c9596b4146b140a986d..54783e8eb8bc7d1254d93c96557495489a23fd03 100644
--- a/src/dir_mem.c
+++ b/src/dir_mem.c
@@ -123,7 +123,7 @@ static int item(struct dir *dir, const char *name, struct dir_ext *ext) {
 
   if(!extended_info)
     dir->flags &= ~FF_EXT;
-  item = malloc(dir->flags & FF_EXT ? dir_ext_memsize(name) : dir_memsize(name));
+  item = xmalloc(dir->flags & FF_EXT ? dir_ext_memsize(name) : dir_memsize(name));
   memcpy(item, dir, offsetof(struct dir, name));
   strcpy(item->name, name);
   if(dir->flags & FF_EXT)
diff --git a/src/dir_scan.c b/src/dir_scan.c
index 442c4a278de0a6be117cc773e9967bb27ae16228..6f65aabe79879f14792def02c64365c955bc8a0b 100644
--- a/src/dir_scan.c
+++ b/src/dir_scan.c
@@ -100,7 +100,7 @@ static char *dir_read(int *err) {
     return NULL;
   }
 
-  buf = malloc(buflen);
+  buf = xmalloc(buflen);
   errno = 0;
 
   while((item = readdir(dir)) != NULL) {
@@ -109,7 +109,7 @@ static char *dir_read(int *err) {
     int req = off+3+strlen(item->d_name);
     if(req > buflen) {
       buflen = req < buflen*2 ? buflen*2 : req;
-      buf = realloc(buf, buflen);
+      buf = xrealloc(buf, buflen);
     }
     strcpy(buf+off, item->d_name);
     off += strlen(item->d_name)+1;
@@ -313,6 +313,6 @@ void dir_scan_init(const char *path) {
   dir_seterr(NULL);
   dir_process = process;
   if (!buf_dir)
-    buf_dir = malloc(dir_memsize(""));
+    buf_dir = xmalloc(dir_memsize(""));
   pstate = ST_CALC;
 }
diff --git a/src/dirlist.c b/src/dirlist.c
index 2f8f3232ddee77f87dc2680bf14a6240a70a3b4f..86cf4febeb6c11d5adb4eabb16fb8501f253df1f 100644
--- a/src/dirlist.c
+++ b/src/dirlist.c
@@ -217,7 +217,7 @@ void dirlist_open(struct dir *d) {
   /* set the reference to the parent dir */
   if(d->parent) {
     if(!parent_alloc)
-      parent_alloc = calloc(1, dir_memsize(".."));
+      parent_alloc = xcalloc(1, dir_memsize(".."));
     dirlist_parent = parent_alloc;
     strcpy(dirlist_parent->name, "..");
     dirlist_parent->next = head;
diff --git a/src/exclude.c b/src/exclude.c
index f417c92ba9f1dc1bb02d0c78c8a583321b12aebe..460543a65c979b232d8267be7203f7043ffd9cce 100644
--- a/src/exclude.c
+++ b/src/exclude.c
@@ -23,7 +23,7 @@
 
 */
 
-#include "exclude.h"
+#include "global.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -45,8 +45,8 @@ void exclude_add(char *pat) {
   while(*n != NULL)
     n = &((*n)->next);
 
-  *n = (struct exclude *) calloc(1, sizeof(struct exclude));
-  (*n)->pattern = (char *) malloc(strlen(pat)+1);
+  *n = (struct exclude *) xcalloc(1, sizeof(struct exclude));
+  (*n)->pattern = (char *) xmalloc(strlen(pat)+1);
   strcpy((*n)->pattern, pat);
 }
 
@@ -125,7 +125,7 @@ int has_cachedir_tag(const char *name) {
     /* We don't need to copy the content of `path`, so it's more efficient to
      * use `free` + `malloc`. */
     free(path);
-    path = malloc(path_l);
+    path = xmalloc(path_l);
   }
   snprintf(path, path_l, "%s/%s", name, CACHEDIR_TAG_FILENAME);
   f = fopen(path, "rb");
diff --git a/src/global.h b/src/global.h
index 90b804af0a0e44b8b466b054f0db08259a180387..b544ea74e16d8a75c87f18a71855491b9c12dff4 100644
--- a/src/global.h
+++ b/src/global.h
@@ -109,6 +109,9 @@ extern int follow_symlinks;
 /* handle input from keyboard and update display */
 int input_handle(int);
 
+/* de-initialize ncurses */
+void close_nc();
+
 
 /* import all other global functions and variables */
 #include "browser.h"
diff --git a/src/main.c b/src/main.c
index a9f4bdcd9671a7fccda82df2a009f36f86dd7cfa..6ce951d6f30e9c4a62cd95e679f9e7ac86bc1cca 100644
--- a/src/main.c
+++ b/src/main.c
@@ -280,6 +280,15 @@ static void init_nc() {
 }
 
 
+void close_nc() {
+  if(ncurses_init) {
+    erase();
+    refresh();
+    endwin();
+  }
+}
+
+
 /* main program */
 int main(int argc, char **argv) {
   read_locale();
@@ -309,11 +318,7 @@ int main(int argc, char **argv) {
       break;
   }
 
-  if(ncurses_init) {
-    erase();
-    refresh();
-    endwin();
-  }
+  close_nc();
   exclude_clear();
 
   return 0;
diff --git a/src/path.c b/src/path.c
index 87227f39f4a48c3858564d26481f83c431f7bde8..0a5f63743e1a7add48effcc095002406a0948be4 100644
--- a/src/path.c
+++ b/src/path.c
@@ -23,7 +23,7 @@
 
 */
 
-#include "path.h"
+#include "global.h"
 
 #include <string.h>
 #include <stdio.h>
@@ -64,8 +64,8 @@ static int path_split(char *cur, char ***res) {
     }
 
   /* create array of the components */
-  old = malloc((j+1)*sizeof(char *));
-  *res = malloc((j+1)*sizeof(char *));
+  old = xmalloc((j+1)*sizeof(char *));
+  *res = xmalloc((j+1)*sizeof(char *));
   for(i=j=0; i<n; i++)
     if(i == 0 || (cur[i-1] == 0 && cur[i] != 0))
       old[j++] = cur+i;
@@ -98,11 +98,11 @@ static char *path_absolute(const char *path) {
   /* not an absolute path? prepend cwd */
   if(path[0] != '/') {
     n = RPATH_CNKSZ;
-    ret = malloc(n);
+    ret = xmalloc(n);
     errno = 0;
     while(!getcwd(ret, n) && errno == ERANGE) {
       n += RPATH_CNKSZ;
-      ret = realloc(ret, n);
+      ret = xrealloc(ret, n);
       errno = 0;
     }
     if(errno) {
@@ -112,12 +112,12 @@ static char *path_absolute(const char *path) {
 
     i = strlen(path) + strlen(ret) + 2;
     if(i > n)
-      ret = realloc(ret, i);
+      ret = xrealloc(ret, i);
     strcat(ret, "/");
     strcat(ret, path);
   /* otherwise, just make a copy */
   } else {
-    ret = malloc(strlen(path)+1);
+    ret = xmalloc(strlen(path)+1);
     strcpy(ret, path);
   }
   return ret;
@@ -133,7 +133,7 @@ static char *path_real_rec(char *cur, int *links) {
   char **arr, *tmp, *lnk = NULL, *ret = NULL;
 
   tmpl = strlen(cur)+1;
-  tmp = malloc(tmpl);
+  tmp = xmalloc(tmpl);
 
   /* split path */
   i = path_split(cur, &arr);
@@ -142,7 +142,7 @@ static char *path_real_rec(char *cur, int *links) {
   strcpy(tmp, "/");
   if(i > 0) {
     lnkl = RPATH_CNKSZ;
-    lnk = malloc(lnkl);
+    lnk = xmalloc(lnkl);
     if(chdir("/") < 0)
       goto path_real_done;
   }
@@ -153,7 +153,7 @@ static char *path_real_rec(char *cur, int *links) {
     /* check for symlink */
     while((n = readlink(arr[i], lnk, lnkl)) == lnkl || (n < 0 && errno == ERANGE)) {
       lnkl += RPATH_CNKSZ;
-      lnk = realloc(lnk, lnkl);
+      lnk = xrealloc(lnk, lnkl);
     }
     if(n < 0 && errno != EINVAL)
       goto path_real_done;
@@ -168,7 +168,7 @@ static char *path_real_rec(char *cur, int *links) {
         n += strlen(tmp);
       if(tmpl < n) {
         tmpl = n;
-        tmp = realloc(tmp, tmpl);
+        tmp = xrealloc(tmp, tmpl);
       }
       if(lnk[0] != '/')
         strcat(tmp, lnk);
@@ -179,7 +179,7 @@ static char *path_real_rec(char *cur, int *links) {
         n += strlen(arr[i])+1;
         if(tmpl < n) {
           tmpl = n;
-          tmp = realloc(tmp, tmpl);
+          tmp = xrealloc(tmp, tmpl);
         }
         strcat(tmp, "/");
         strcat(tmp, arr[i]);
diff --git a/src/path.h b/src/path.h
index 6ed9a354baadf6cdf1f37ec674582e21022827bf..e9d91cc06d3ebf7038895581ec8715f29fd7470d 100644
--- a/src/path.h
+++ b/src/path.h
@@ -30,7 +30,6 @@
   - path_real uses chdir(), so it's not thread safe
   - Process requires +x access for all directory components
   - Potentionally slow
-  - Doesn't check return value of malloc() and realloc()
   - path_real doesn't check for the existance of the last component
   - cwd is unreliable after path_real
 */
diff --git a/src/util.c b/src/util.c
index d99a42d8489c8791aad319d993a247050489be06..c62e9bdaa2349eaaecfbe1ebf50eecf3f6e9c6fe 100644
--- a/src/util.c
+++ b/src/util.c
@@ -29,6 +29,7 @@
 #include <stdlib.h>
 #include <ncurses.h>
 #include <stdarg.h>
+#include <unistd.h>
 #ifdef HAVE_LOCALE_H
 #include <locale.h>
 #endif
@@ -371,12 +372,12 @@ char *getpath(struct dir *cur) {
 
   if(datl == 0) {
     datl = i;
-    dat = malloc(i);
+    dat = xmalloc(i);
   } else if(datl < i) {
     datl = i;
-    dat = realloc(dat, i);
+    dat = xrealloc(dat, i);
   }
-  list = malloc(c*sizeof(struct dir *));
+  list = xmalloc(c*sizeof(struct dir *));
 
   c = 0;
   for(d=cur; d!=NULL; d=d->parent)
@@ -413,3 +414,21 @@ void addparentstats(struct dir *d, int64_t size, int64_t asize, uint64_t mtime,
     d = d->parent;
   }
 }
+
+
+/* Apparently we can just resume drawing after endwin() and ncurses will pick
+ * up where it left. Probably not very portable...  */
+#define oom_msg "\nOut of memory, press enter to try again or Ctrl-C to give up.\n"
+#define wrap_oom(f) \
+  void *ptr;\
+  char buf[128];\
+  while((ptr = f) == NULL) {\
+    close_nc();\
+    write(2, oom_msg, sizeof(oom_msg));\
+    read(0, buf, sizeof(buf));\
+  }\
+  return ptr;
+
+void *xmalloc(size_t size) { wrap_oom(malloc(size)) }
+void *xcalloc(size_t n, size_t size) { wrap_oom(calloc(n, size)) }
+void *xrealloc(void *mem, size_t size) { wrap_oom(realloc(mem, size)) }
diff --git a/src/util.h b/src/util.h
index 50344e350a7dcccd889f9ec2c42d5be858f01f06..f3c692554d01e6dd6dd871f0e9f911d1aa87bb05 100644
--- a/src/util.h
+++ b/src/util.h
@@ -170,13 +170,13 @@ void addparentstats(struct dir *, int64_t, int64_t, uint64_t, int);
 #define nstack_init(_s) do {\
     (_s)->size = 10;\
     (_s)->top = 0;\
-    (_s)->list = malloc(10*sizeof(*(_s)->list));\
+    (_s)->list = xmalloc(10*sizeof(*(_s)->list));\
   } while(0)
 
 #define nstack_push(_s, _v) do {\
     if((_s)->size <= (_s)->top) {\
       (_s)->size *= 2;\
-      (_s)->list = realloc((_s)->list, (_s)->size*sizeof(*(_s)->list));\
+      (_s)->list = xrealloc((_s)->list, (_s)->size*sizeof(*(_s)->list));\
     }\
     (_s)->list[(_s)->top++] = _v;\
   } while(0)
@@ -186,5 +186,10 @@ void addparentstats(struct dir *, int64_t, int64_t, uint64_t, int);
 #define nstack_free(_s) free((_s)->list)
 
 
+/* Malloc wrappers that exit on OOM */
+void *xmalloc();
+void *xcalloc(size_t, size_t);
+void *xrealloc(void *, size_t);
+
 #endif