- use ZDoom's memory allocation wrapper instead of EDuke's.

This simply plays nicer with the compiler's diagnostics.
This commit is contained in:
Christoph Oelckers 2020-04-11 23:46:42 +02:00
parent 66ecb05eb8
commit 797640c494
7 changed files with 283 additions and 150 deletions

View file

@ -717,6 +717,7 @@ set (PCH_SOURCES
core/utility/i_module.cpp core/utility/i_module.cpp
core/utility/i_time.cpp core/utility/i_time.cpp
core/utility/name.cpp core/utility/name.cpp
core/utility/m_alloc.cpp
core/utility/cmdlib.cpp core/utility/cmdlib.cpp
core/utility/m_argv.cpp core/utility/m_argv.cpp
core/utility/files.cpp core/utility/files.cpp

View file

@ -8,6 +8,7 @@
#pragma once #pragma once
#include "xs_Float.h" #include "xs_Float.h"
#include "m_alloc.h"
////////// Compiler detection ////////// ////////// Compiler detection //////////
@ -986,7 +987,11 @@ static inline void append_ext_UNSAFE(char *outbuf, const char *ext)
////////// String manipulation ////////// ////////// String manipulation //////////
char *Bstrtolower(char *str); inline char* Bstrtolower(char* str)
{
if (str) for (int i = 0; str[i]; i++) str[i] = tolower(str[i]);
return str;
}
////////// Miscellaneous ////////// ////////// Miscellaneous //////////
@ -1002,102 +1007,16 @@ extern void xalloc_set_location(int32_t line, const char *file, const char *func
void set_memerr_handler(void (*handlerfunc)(int32_t, const char *, const char *)); void set_memerr_handler(void (*handlerfunc)(int32_t, const char *, const char *));
void *handle_memerr(void *); void *handle_memerr(void *);
static FORCE_INLINE char *xstrdup(const char *s)
{
char *ptr = strdup(s);
return (EDUKE32_PREDICT_TRUE(ptr != NULL)) ? ptr : (char *)handle_memerr(ptr);
}
static FORCE_INLINE void *xmalloc(const bsize_t size)
{
void *ptr = Bmalloc(size);
return (EDUKE32_PREDICT_TRUE(ptr != NULL)) ? ptr : handle_memerr(ptr);
}
static FORCE_INLINE void *xcalloc(const bsize_t nmemb, const bsize_t size)
{
void *ptr = Bcalloc(nmemb, size);
return (EDUKE32_PREDICT_TRUE(ptr != NULL)) ? ptr : handle_memerr(ptr);
}
static FORCE_INLINE void *xrealloc(void * const ptr, const 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:
return (EDUKE32_PREDICT_TRUE(newptr != NULL || size == 0)) ? newptr: handle_memerr(ptr);
}
static FORCE_INLINE void xfree(void *const ptr) { free(ptr); }
static FORCE_INLINE void xaligned_free(void *const ptr) { Baligned_free(ptr); }
#if !defined NO_ALIGNED_MALLOC
static FORCE_INLINE void *xaligned_alloc(const bsize_t alignment, const bsize_t size)
{
void *ptr = Baligned_alloc(alignment, size);
return (EDUKE32_PREDICT_TRUE(ptr != NULL)) ? ptr : handle_memerr(ptr);
}
static FORCE_INLINE void *xaligned_calloc(const bsize_t alignment, const bsize_t count, const bsize_t size)
{
bsize_t const blocksize = count * size;
void *ptr = Baligned_alloc(alignment, blocksize);
if (EDUKE32_PREDICT_TRUE(ptr != NULL))
{
Bmemset(ptr, 0, blocksize);
return ptr;
}
return handle_memerr(ptr);
}
#else
# define xaligned_alloc(alignment, size) xmalloc(size)
# define xaligned_calloc(alignment, count, size) xcalloc(count, size)
#endif
#ifdef DEBUGGINGAIDS
# define EDUKE32_PRE_XALLOC xalloc_set_location(__LINE__, __FILE__, EDUKE32_FUNCTION),
#else
# define EDUKE32_PRE_XALLOC
#endif
#ifndef _DEBUG
#define Xstrdup(s) (EDUKE32_PRE_XALLOC xstrdup(s))
#define Xmalloc(size) (EDUKE32_PRE_XALLOC xmalloc(size))
#define Xcalloc(nmemb, size) (EDUKE32_PRE_XALLOC xcalloc(nmemb, size))
#define Xrealloc(ptr, size) (EDUKE32_PRE_XALLOC xrealloc(ptr, size))
#define Xaligned_alloc(alignment, size) (EDUKE32_PRE_XALLOC xaligned_alloc(alignment, size))
#define Xaligned_calloc(alignment, count, size) (EDUKE32_PRE_XALLOC xaligned_calloc(alignment, count, size))
#define Xfree(ptr) (EDUKE32_PRE_XALLOC xfree(ptr))
#define Xaligned_free(ptr) (EDUKE32_PRE_XALLOC xaligned_free(ptr))
#else
// This is for allowing the compiler's heap checker to do its job. When wrapped it only points to the wrapper for a memory leak, not to the real location where the allocation takes place. // This is for allowing the compiler's heap checker to do its job. When wrapped it only points to the wrapper for a memory leak, not to the real location where the allocation takes place.
#define Xstrdup(s) (strdup(s)) #define Xstrdup(s) (strdup(s))
#define Xmalloc(size) (malloc(size)) #define Xmalloc(size) (M_Malloc(size))
#define Xcalloc(nmemb, size) (calloc(nmemb, size)) #define Xcalloc(nmemb, size) (M_Calloc(nmemb, size))
#define Xrealloc(ptr, size) (realloc(ptr, size)) #define Xrealloc(ptr, size) (M_Realloc(ptr, size))
#define Xaligned_alloc(alignment, size) (malloc(size)) #define Xaligned_alloc(alignment, size) (M_Malloc(size))
#define Xaligned_calloc(alignment, count, size) (calloc(count, size)) #define Xaligned_calloc(alignment, count, size) (M_Calloc(count, size))
#define Xfree(ptr) (free(ptr)) #define Xfree(ptr) (M_Free(ptr))
#define Xaligned_free(ptr) (free(ptr)) #define Xaligned_free(ptr) (M_Free(ptr))
#endif
////////// More utility functions //////////
static inline void maybe_grow_buffer(char ** const buffer, int32_t * const buffersize, int32_t const newsize)
{
if (newsize > *buffersize)
{
*buffer = (char *)Xrealloc(*buffer, newsize);
*buffersize = newsize;
}
}
////////// Inlined external libraries ////////// ////////// Inlined external libraries //////////

View file

@ -9,52 +9,4 @@
#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
void *handle_memerr(void *p)
{
UNREFERENCED_PARAMETER(p);
debug_break();
if (g_MemErrHandler)
{
#ifdef DEBUGGINGAIDS
g_MemErrHandler(g_MemErrLine, g_MemErrFile, g_MemErrFunc);
#else
g_MemErrHandler(0, "???", "???");
#endif
}
Bexit(EXIT_FAILURE);
EDUKE32_UNREACHABLE_SECTION(return &handle_memerr);
}
void set_memerr_handler(void(*handlerfunc)(int32_t, const char *, const char *))
{
g_MemErrHandler = handlerfunc;
}
char *Bstrtolower(char *str)
{
if (str) for (int i = 0; str[i]; i++) str[i] = tolower(str[i]);
return str;
}

View file

@ -362,8 +362,6 @@ int RunGame();
int GameMain() int GameMain()
{ {
set_memerr_handler(G_HandleMemErr);
int r; int r;
try try
{ {
@ -707,11 +705,6 @@ int RunGame()
return gi->app_main(); return gi->app_main();
} }
void G_HandleMemErr(int32_t lineNum, const char* fileName, const char* funcName)
{
I_FatalError("Out of memory in %s:%d (%s)\n", fileName, lineNum, funcName);
}
void G_FatalEngineError(void) void G_FatalEngineError(void)
{ {
I_FatalError("There was a problem initializing the engine: %s\n\nThe application will now close.", engineerrstr); I_FatalError("There was a problem initializing the engine: %s\n\nThe application will now close.", engineerrstr);

View file

@ -158,7 +158,6 @@ const char* G_ConFile(void);
TArray<GrpEntry> GrpScan(); TArray<GrpEntry> GrpScan();
void S_SetSoundPaused(int state); void S_SetSoundPaused(int state);
void G_HandleMemErr(int32_t lineNum, const char* fileName, const char* funcName);
void G_FatalEngineError(void); void G_FatalEngineError(void);
int CalcSmoothRatio(const ClockTicks& totalclk, const ClockTicks& ototalclk, int realgameticspersec); int CalcSmoothRatio(const ClockTicks& totalclk, const ClockTicks& ototalclk, int realgameticspersec);

View file

@ -0,0 +1,188 @@
/*
** m_alloc.cpp
** Wrappers for the malloc family of functions that count used bytes.
**
**---------------------------------------------------------------------------
** Copyright 1998-2008 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#if defined(__FreeBSD__)
#include <stdlib.h>
#include <malloc_np.h>
#elif defined(__APPLE__)
#include <stdlib.h>
#include <malloc/malloc.h>
#elif defined(__OpenBSD__)
#include <stdlib.h>
#else
#include <malloc.h>
#endif
#include "printf.h"
#include "m_alloc.h"
#ifndef _MSC_VER
#define _NORMAL_BLOCK 0
#define _malloc_dbg(s,b,f,l) malloc(s)
#define _realloc_dbg(p,s,b,f,l) realloc(p,s)
#endif
#ifndef _DEBUG
#if !defined(__solaris__) && !defined(__OpenBSD__)
void *M_Malloc(size_t size)
{
void *block = malloc(size);
if (block == NULL)
I_FatalError("Could not malloc %zu bytes", size);
return block;
}
void *M_Realloc(void *memblock, size_t size)
{
void *block = realloc(memblock, size);
if (block == NULL)
{
I_FatalError("Could not realloc %zu bytes", size);
}
return block;
}
#else
void *M_Malloc(size_t size)
{
void *block = malloc(size+sizeof(size_t));
if (block == NULL)
I_FatalError("Could not malloc %zu bytes", size);
size_t *sizeStore = (size_t *) block;
*sizeStore = size;
block = sizeStore+1;
return block;
}
void *M_Realloc(void *memblock, size_t size)
{
if(memblock == NULL)
return M_Malloc(size);
void *block = realloc(((size_t*) memblock)-1, size+sizeof(size_t));
if (block == NULL)
{
I_FatalError("Could not realloc %zu bytes", size);
}
size_t *sizeStore = (size_t *) block;
*sizeStore = size;
block = sizeStore+1;
return block;
}
#endif
#else
#ifdef _MSC_VER
#include <crtdbg.h>
#endif
#if !defined(__solaris__) && !defined(__OpenBSD__)
void *M_Malloc_Dbg(size_t size, const char *file, int lineno)
{
void *block = _malloc_dbg(size, _NORMAL_BLOCK, file, lineno);
if (block == NULL)
I_FatalError("Could not malloc %zu bytes in %s, line %d", size, file, lineno);
return block;
}
void *M_Realloc_Dbg(void *memblock, size_t size, const char *file, int lineno)
{
void *block = _realloc_dbg(memblock, size, _NORMAL_BLOCK, file, lineno);
if (block == NULL)
{
I_FatalError("Could not realloc %zu bytes in %s, line %d", size, file, lineno);
}
return block;
}
#else
void *M_Malloc_Dbg(size_t size, const char *file, int lineno)
{
void *block = _malloc_dbg(size+sizeof(size_t), _NORMAL_BLOCK, file, lineno);
if (block == NULL)
I_FatalError("Could not malloc %zu bytes in %s, line %d", size, file, lineno);
size_t *sizeStore = (size_t *) block;
*sizeStore = size;
block = sizeStore+1;
return block;
}
void *M_Realloc_Dbg(void *memblock, size_t size, const char *file, int lineno)
{
if(memblock == NULL)
return M_Malloc_Dbg(size, file, lineno);
void *block = _realloc_dbg(((size_t*) memblock)-1, size+sizeof(size_t), _NORMAL_BLOCK, file, lineno);
if (block == NULL)
{
I_FatalError("Could not realloc %zu bytes in %s, line %d", size, file, lineno);
}
size_t *sizeStore = (size_t *) block;
*sizeStore = size;
block = sizeStore+1;
return block;
}
#endif
#endif
#if !defined(__solaris__) && !defined(__OpenBSD__)
void M_Free (void *block)
{
if (block != NULL)
{
free(block);
}
}
#else
void M_Free (void *block)
{
if(block != NULL)
{
free(((size_t*) block)-1);
}
}
#endif

View file

@ -0,0 +1,81 @@
/*
** m_alloc.h
**
**---------------------------------------------------------------------------
** Copyright 1998-2008 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#ifndef __M_ALLOC_H__
#define __M_ALLOC_H__
#include <stdlib.h>
#include <string.h>
#if defined(__APPLE__)
#define _msize(p) malloc_size(p)
#elif defined(__solaris__) || defined(__OpenBSD__)
#define _msize(p) (*((size_t*)(p)-1))
#elif !defined(_WIN32)
#define _msize(p) malloc_usable_size(p) // from glibc/FreeBSD
#endif
// These are the same as the same stdlib functions,
// except they bomb out with a fatal error
// when they can't get the memory.
#if defined(_DEBUG)
#define M_Calloc(s,t) M_Calloc_Dbg(s, t, __FILE__, __LINE__)
#define M_Malloc(s) M_Malloc_Dbg(s, __FILE__, __LINE__)
#define M_Realloc(p,s) M_Realloc_Dbg(p, s, __FILE__, __LINE__)
void *M_Malloc_Dbg (size_t size, const char *file, int lineno);
void *M_Realloc_Dbg (void *memblock, size_t size, const char *file, int lineno);
inline void* M_Calloc_Dbg(size_t v1, size_t v2, const char* file, int lineno)
{
auto p = M_Malloc_Dbg(v1 * v2, file, lineno);
memset(p, 0, v1 * v2);
return p;
}
#else
void *M_Malloc (size_t size);
void *M_Realloc (void *memblock, size_t size);
inline void* M_Calloc(size_t v1, size_t v2)
{
auto p = M_Malloc(v1 * v2);
memset(p, 0, v1 * v2);
return p;
}
#endif
void M_Free (void *memblock);
#endif //__M_ALLOC_H__