diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp
index 72452f9c2..984c7138a 100644
--- a/src/client/clientlauncher.cpp
+++ b/src/client/clientlauncher.cpp
@@ -277,9 +277,8 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
 
 #ifdef NDEBUG
 		catch (std::exception &e) {
-			std::string error_message = "Some exception: \"";
-			error_message += e.what();
-			error_message += "\"";
+			error_message = "Some exception: ";
+			error_message.append(debug_describe_exc(e));
 			errorstream << error_message << std::endl;
 		}
 #endif
diff --git a/src/debug.cpp b/src/debug.cpp
index 3c82ed9e1..04d59a6d7 100644
--- a/src/debug.cpp
+++ b/src/debug.cpp
@@ -32,6 +32,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #ifdef _MSC_VER
 	#include <dbghelp.h>
+	#include <windows.h>
+	#include <eh.h>
 	#include "version.h"
 	#include "filesys.h"
 #endif
@@ -74,6 +76,13 @@ void fatal_error_fn(const char *msg, const char *file,
 	abort();
 }
 
+std::string debug_describe_exc(const std::exception &e)
+{
+	if (dynamic_cast<const std::bad_alloc*>(&e))
+		return "C++ out of memory";
+	return std::string("\"").append(e.what()).append("\"");
+}
+
 #ifdef _MSC_VER
 
 const char *Win32ExceptionCodeToString(DWORD exception_code)
diff --git a/src/debug.h b/src/debug.h
index fcef2091c..aeea81d47 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -25,11 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "gettime.h"
 #include "log.h"
 
-#ifdef _WIN32
-	#include <windows.h>
-	#ifdef _MSC_VER
-		#include <eh.h>
-	#endif
+#ifdef _MSC_VER
 	#define FUNCTION_NAME __FUNCTION__
 #else
 	#define FUNCTION_NAME __PRETTY_FUNCTION__
@@ -75,6 +71,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #define sanity_check(expr) SANITY_CHECK(expr)
 
+std::string debug_describe_exc(const std::exception &e);
 
 void debug_set_exception_handler();
 
@@ -86,9 +83,10 @@ void debug_set_exception_handler();
 	#define BEGIN_DEBUG_EXCEPTION_HANDLER try {
 	#define END_DEBUG_EXCEPTION_HANDLER                        \
 		} catch (std::exception &e) {                          \
+			std::string e_descr = debug_describe_exc(e);       \
 			errorstream << "An unhandled exception occurred: " \
-				<< e.what() << std::endl;                      \
-			FATAL_ERROR(e.what());                             \
+				<< e_descr << std::endl;                       \
+			FATAL_ERROR(e_descr.c_str());                      \
 		}
 #else
 	// Dummy ones
diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp
index 311d94c6e..b02591f3a 100644
--- a/src/script/common/c_internal.cpp
+++ b/src/script/common/c_internal.cpp
@@ -42,7 +42,8 @@ int script_exception_wrapper(lua_State *L, lua_CFunction f)
 	} catch (const char *s) {  // Catch and convert exceptions.
 		lua_pushstring(L, s);
 	} catch (std::exception &e) {
-		lua_pushstring(L, e.what());
+		std::string e_descr = debug_describe_exc(e);
+		lua_pushlstring(L, e_descr.c_str(), e_descr.size());
 	}
 	return lua_error(L);  // Rethrow as a Lua error.
 }