mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-25 11:10:47 +00:00
Add X{m,c,re}alloc and Xstrdup macros that call an out-of-memory handler on failure.
These wrap the x*alloc or xstrdup functions in compat.c. The handler gets passed __FILE__, __LINE__ and __func__ (if available) in debugging builds. Terminating the application process immediately in case of allocation failure will let us prune many error handling paths and simplify a good portion of code. git-svn-id: https://svn.eduke32.com/eduke32@4490 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
95a6c01045
commit
1d26121514
4 changed files with 128 additions and 0 deletions
|
@ -775,6 +775,15 @@ static inline void append_ext_UNSAFE(char *outbuf, const char *ext)
|
|||
Bstrcpy(p, ext);
|
||||
}
|
||||
|
||||
#ifdef DEBUGGINGAIDS
|
||||
extern void xalloc_set_location(int32_t line, const char *file, const char *func);
|
||||
#endif
|
||||
void set_memerr_handler(void (*handlerfunc)(int32_t, const char *, const char *));
|
||||
char *xstrdup(const char *s);
|
||||
void *xmalloc(bsize_t size);
|
||||
void *xcalloc(bsize_t nmemb, bsize_t size);
|
||||
void *xrealloc(void *ptr, bsize_t size);
|
||||
|
||||
#ifdef EXTERNC
|
||||
}
|
||||
#endif
|
||||
|
@ -839,5 +848,29 @@ static inline void append_ext_UNSAFE(char *outbuf, const char *ext)
|
|||
#define ARRAY_SIZE(Ar) (sizeof(Ar)/sizeof((Ar)[0]))
|
||||
#define ARRAY_SSIZE(Ar) (bssize_t)ARRAY_SIZE(Ar)
|
||||
|
||||
////////// PANICKING ALLOCATION MACROS (wrapping the functions) //////////
|
||||
#ifdef DEBUGGINGAIDS
|
||||
// Detection of __func__ or equivalent functionality, found in SDL_assert.h
|
||||
# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */
|
||||
# define EDUKE32_FUNCTION __func__
|
||||
# elif ((__GNUC__ >= 2) || defined(_MSC_VER))
|
||||
# define EDUKE32_FUNCTION __FUNCTION__
|
||||
# else
|
||||
# define EDUKE32_FUNCTION "???"
|
||||
# endif
|
||||
|
||||
# define EDUKE32_PRE_XALLLOC xalloc_set_location(__LINE__, __FILE__, EDUKE32_FUNCTION)
|
||||
# define Xstrdup(s) (EDUKE32_PRE_XALLLOC, xstrdup(s))
|
||||
# define Xmalloc(size) (EDUKE32_PRE_XALLLOC, xmalloc(size))
|
||||
# define Xcalloc(nmemb, size) (EDUKE32_PRE_XALLLOC, xcalloc(nmemb, size))
|
||||
# define Xrealloc(ptr, size) (EDUKE32_PRE_XALLLOC, xrealloc(ptr, size))
|
||||
#else
|
||||
# define Xstrdup xstrdup
|
||||
# define Xmalloc xmalloc
|
||||
# define Xcalloc xcalloc
|
||||
# define Xrealloc xrealloc
|
||||
#endif
|
||||
//////////
|
||||
|
||||
#endif // __compat_h__
|
||||
|
||||
|
|
|
@ -45,6 +45,84 @@
|
|||
#include "compat.h"
|
||||
#include "baselayer.h"
|
||||
|
||||
////////// PANICKING ALLOCATION FUNCTIONS //////////
|
||||
|
||||
static void (*g_MemErrHandler)(int32_t line, const char *file, const char *func);
|
||||
|
||||
#ifdef DEBUGGINGAIDS
|
||||
static const char *g_MemErrFunc = "???";
|
||||
static const char *g_MemErrFile = "???";
|
||||
static int32_t g_MemErrLine;
|
||||
|
||||
void xalloc_set_location(int32_t line, const char *file, const char *func)
|
||||
{
|
||||
g_MemErrLine = line;
|
||||
g_MemErrFile = file;
|
||||
|
||||
if (func)
|
||||
g_MemErrFunc = func;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void handle_potential_memerr(void *ptr)
|
||||
{
|
||||
if (ptr == NULL)
|
||||
{
|
||||
if (g_MemErrHandler)
|
||||
{
|
||||
#ifdef DEBUGGINGAIDS
|
||||
g_MemErrHandler(g_MemErrLine, g_MemErrFile, g_MemErrFunc);
|
||||
#else
|
||||
g_MemErrHandler(0, "???", "???");
|
||||
#endif
|
||||
}
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void set_memerr_handler(void (*handlerfunc)(int32_t, const char *, const char *))
|
||||
{
|
||||
g_MemErrHandler = handlerfunc;
|
||||
}
|
||||
|
||||
char *xstrdup(const char *s)
|
||||
{
|
||||
char *ptr = Bstrdup(s);
|
||||
handle_potential_memerr(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *xmalloc(bsize_t size)
|
||||
{
|
||||
void *ptr = Bmalloc(size);
|
||||
handle_potential_memerr(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *xcalloc(bsize_t nmemb, bsize_t size)
|
||||
{
|
||||
void *ptr = Bcalloc(nmemb, size);
|
||||
handle_potential_memerr(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *xrealloc(void *ptr, bsize_t size)
|
||||
{
|
||||
void *newptr = Brealloc(ptr, size);
|
||||
|
||||
// According to the C Standard,
|
||||
// - ptr == NULL makes realloc() behave like malloc()
|
||||
// - size == 0 make it behave like free() if ptr != NULL
|
||||
// Since we want to catch an out-of-mem in the first case, this leaves:
|
||||
if (size != 0)
|
||||
handle_potential_memerr(newptr);
|
||||
|
||||
return newptr;
|
||||
}
|
||||
|
||||
//////////
|
||||
|
||||
#ifndef __compat_h_macrodef__
|
||||
|
||||
void Bassert(int expr)
|
||||
|
|
|
@ -10403,12 +10403,20 @@ static void m32script_interrupt_handler(int signo)
|
|||
}
|
||||
}
|
||||
|
||||
static void M32_HandleMemErr(int32_t line, const char *file, const char *func)
|
||||
{
|
||||
initprintf("Out of memory in %s:%d (%s)\n", file, line, func);
|
||||
osdcmd_quit(NULL);
|
||||
}
|
||||
|
||||
int32_t ExtInit(void)
|
||||
{
|
||||
int32_t rv = 0;
|
||||
int32_t i;
|
||||
char cwd[BMAX_PATH];
|
||||
|
||||
set_memerr_handler(&M32_HandleMemErr);
|
||||
|
||||
G_AddSearchPaths();
|
||||
|
||||
if (getcwd(cwd,BMAX_PATH))
|
||||
|
|
|
@ -10822,10 +10822,19 @@ void G_PostCreateGameState(void)
|
|||
A_InitEnemyFlags();
|
||||
}
|
||||
|
||||
static void G_HandleMemErr(int32_t line, const char *file, const char *func)
|
||||
{
|
||||
static char msg[128];
|
||||
snprintf(msg, sizeof(msg), "Out of memory in %s:%d (%s)\n", file, line, func);
|
||||
G_GameExit(msg);
|
||||
}
|
||||
|
||||
static void G_Startup(void)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
set_memerr_handler(&G_HandleMemErr);
|
||||
|
||||
inittimer(TICRATE);
|
||||
|
||||
initcrc32table();
|
||||
|
|
Loading…
Reference in a new issue