mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-26 03:30:46 +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);
|
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
|
#ifdef EXTERNC
|
||||||
}
|
}
|
||||||
#endif
|
#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_SIZE(Ar) (sizeof(Ar)/sizeof((Ar)[0]))
|
||||||
#define ARRAY_SSIZE(Ar) (bssize_t)ARRAY_SIZE(Ar)
|
#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__
|
#endif // __compat_h__
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,84 @@
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "baselayer.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__
|
#ifndef __compat_h_macrodef__
|
||||||
|
|
||||||
void Bassert(int expr)
|
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 ExtInit(void)
|
||||||
{
|
{
|
||||||
int32_t rv = 0;
|
int32_t rv = 0;
|
||||||
int32_t i;
|
int32_t i;
|
||||||
char cwd[BMAX_PATH];
|
char cwd[BMAX_PATH];
|
||||||
|
|
||||||
|
set_memerr_handler(&M32_HandleMemErr);
|
||||||
|
|
||||||
G_AddSearchPaths();
|
G_AddSearchPaths();
|
||||||
|
|
||||||
if (getcwd(cwd,BMAX_PATH))
|
if (getcwd(cwd,BMAX_PATH))
|
||||||
|
|
|
@ -10822,10 +10822,19 @@ void G_PostCreateGameState(void)
|
||||||
A_InitEnemyFlags();
|
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)
|
static void G_Startup(void)
|
||||||
{
|
{
|
||||||
int32_t i;
|
int32_t i;
|
||||||
|
|
||||||
|
set_memerr_handler(&G_HandleMemErr);
|
||||||
|
|
||||||
inittimer(TICRATE);
|
inittimer(TICRATE);
|
||||||
|
|
||||||
initcrc32table();
|
initcrc32table();
|
||||||
|
|
Loading…
Reference in a new issue