You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
324 lines
7.6 KiB
324 lines
7.6 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: This header, which must be the final include in a .cpp (or .h) file, |
|
// causes all crt methods to use debugging versions of the memory allocators. |
|
// NOTE: Use memdbgoff.h to disable memory debugging. |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
// SPECIAL NOTE! This file must *not* use include guards; we need to be able |
|
// to include this potentially multiple times (since we can deactivate debugging |
|
// by including memdbgoff.h) |
|
|
|
#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) |
|
|
|
// SPECIAL NOTE #2: This must be the final include in a .cpp or .h file!!! |
|
|
|
#if defined(_DEBUG) && !defined(USE_MEM_DEBUG) |
|
#define USE_MEM_DEBUG 1 |
|
#endif |
|
|
|
// If debug build or ndebug and not already included MS custom alloc files, or already included this file |
|
#if (defined(_DEBUG) || !defined(_INC_CRTDBG)) || defined(MEMDBGON_H) |
|
|
|
#include "basetypes.h" |
|
#ifdef _WIN32 |
|
#include <tchar.h> |
|
#else |
|
#include <wchar.h> |
|
#endif |
|
#include <string.h> |
|
#ifdef OSX |
|
#include <malloc/malloc.h> |
|
#else |
|
#include <malloc.h> |
|
#endif |
|
#include "commonmacros.h" |
|
#include "memalloc.h" |
|
|
|
#if defined(USE_MEM_DEBUG) |
|
#if defined( POSIX ) |
|
|
|
#define _NORMAL_BLOCK 1 |
|
|
|
#include <cstddef> |
|
#ifndef ANDROID |
|
#include <glob.h> |
|
#endif |
|
#include <new> |
|
#include <sys/types.h> |
|
#if !defined( DID_THE_OPERATOR_NEW ) |
|
#define DID_THE_OPERATOR_NEW |
|
// posix doesn't have a new of this form, so we impl our own |
|
#ifdef OSX |
|
void* operator new( size_t nSize, int blah, const char *pFileName, int nLine ) throw (std::bad_alloc); |
|
void* operator new[]( size_t nSize, int blah, const char *pFileName, int nLine ) throw (std::bad_alloc); |
|
#else |
|
void* operator new( size_t nSize, int blah, const char *pFileName, int nLine ); |
|
void* operator new[]( size_t nSize, int blah, const char *pFileName, int nLine ); |
|
#endif |
|
#endif |
|
|
|
#else // defined(POSIX) |
|
|
|
// Include crtdbg.h and make sure _DEBUG is set to 1. |
|
#if !defined(_DEBUG) |
|
#define _DEBUG 1 |
|
#include <crtdbg.h> |
|
#undef _DEBUG |
|
#else |
|
#include <crtdbg.h> |
|
#endif // !defined(_DEBUG) |
|
|
|
#endif // defined(POSIX) |
|
#endif |
|
|
|
#include "tier0/memdbgoff.h" |
|
|
|
// -------------------------------------------------------- |
|
// Debug/non-debug agnostic elements |
|
|
|
#define MEM_OVERRIDE_ON 1 |
|
|
|
#undef malloc |
|
#undef realloc |
|
#undef calloc |
|
#undef _expand |
|
#undef free |
|
#undef _msize |
|
#undef _aligned_malloc |
|
#undef _aligned_free |
|
|
|
#ifndef MEMDBGON_H |
|
inline void *MemAlloc_InlineCallocMemset( void *pMem, size_t nCount, size_t nElementSize) |
|
{ |
|
memset(pMem, 0, nElementSize * nCount); |
|
return pMem; |
|
} |
|
#endif |
|
|
|
#define calloc(c, s) MemAlloc_InlineCallocMemset(malloc(c*s), c, s) |
|
#define free(p) g_pMemAlloc->Free( p ) |
|
#define _msize(p) g_pMemAlloc->GetSize( p ) |
|
#define _expand(p, s) _expand_NoLongerSupported(p, s) |
|
#define _aligned_free( p ) MemAlloc_FreeAligned( p ) |
|
|
|
// -------------------------------------------------------- |
|
// Debug path |
|
#if defined(USE_MEM_DEBUG) |
|
|
|
#define malloc(s) g_pMemAlloc->Alloc( s, __FILE__, __LINE__) |
|
#define realloc(p, s) g_pMemAlloc->Realloc( p, s, __FILE__, __LINE__ ) |
|
#define _aligned_malloc( s, a ) MemAlloc_AllocAligned( s, a, __FILE__, __LINE__ ) |
|
|
|
#ifdef _malloc_dbg |
|
#undef _malloc_dbg |
|
#endif |
|
#define _malloc_dbg(s, t, f, l) WHYCALLINGTHISDIRECTLY(s) |
|
|
|
#if !defined( POSIX ) |
|
#if defined(__AFX_H__) && defined(DEBUG_NEW) |
|
#define new DEBUG_NEW |
|
#else |
|
#undef new |
|
#define MEMALL_DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) |
|
#define new MEMALL_DEBUG_NEW |
|
#endif |
|
#endif |
|
|
|
#undef _strdup |
|
#undef strdup |
|
#undef _wcsdup |
|
#undef wcsdup |
|
|
|
#define _strdup(s) MemAlloc_StrDup(s, __FILE__, __LINE__) |
|
#define strdup(s) MemAlloc_StrDup(s, __FILE__, __LINE__) |
|
#define _wcsdup(s) MemAlloc_WcStrDup(s, __FILE__, __LINE__) |
|
#define wcsdup(s) MemAlloc_WcStrDup(s, __FILE__, __LINE__) |
|
|
|
// Make sure we don't define strdup twice |
|
#if !defined(MEMDBGON_H) |
|
|
|
inline char *MemAlloc_StrDup(const char *pString, const char *pFileName, unsigned nLine) |
|
{ |
|
char *pMemory; |
|
|
|
if (!pString) |
|
return NULL; |
|
|
|
size_t len = strlen(pString) + 1; |
|
if ((pMemory = (char *)g_pMemAlloc->Alloc(len, pFileName, nLine)) != NULL) |
|
{ |
|
return strcpy( pMemory, pString ); |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
inline wchar_t *MemAlloc_WcStrDup(const wchar_t *pString, const char *pFileName, unsigned nLine) |
|
{ |
|
wchar_t *pMemory; |
|
|
|
if (!pString) |
|
return NULL; |
|
|
|
size_t len = (wcslen(pString) + 1); |
|
if ((pMemory = (wchar_t *)g_pMemAlloc->Alloc(len * sizeof(wchar_t), pFileName, nLine)) != NULL) |
|
{ |
|
return wcscpy( pMemory, pString ); |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
#endif // DBMEM_DEFINED_STRDUP |
|
|
|
#else |
|
// -------------------------------------------------------- |
|
// Release path |
|
|
|
#define malloc(s) g_pMemAlloc->Alloc( s ) |
|
#define realloc(p, s) g_pMemAlloc->Realloc( p, s ) |
|
#define _aligned_malloc( s, a ) MemAlloc_AllocAligned( s, a ) |
|
|
|
#ifdef _malloc_dbg |
|
#undef _malloc_dbg |
|
#endif |
|
#define _malloc_dbg(s, t, f, l) WHYCALLINGTHISDIRECTLY(s) |
|
|
|
#undef new |
|
|
|
#undef _strdup |
|
#undef strdup |
|
#undef _wcsdup |
|
#undef wcsdup |
|
|
|
#define _strdup(s) MemAlloc_StrDup(s) |
|
#define strdup(s) MemAlloc_StrDup(s) |
|
#define _wcsdup(s) MemAlloc_WcStrDup(s) |
|
#define wcsdup(s) MemAlloc_WcStrDup(s) |
|
|
|
// Make sure we don't define strdup twice |
|
#if !defined(MEMDBGON_H) |
|
|
|
inline char *MemAlloc_StrDup(const char *pString) |
|
{ |
|
char *pMemory; |
|
|
|
if (!pString) |
|
return NULL; |
|
|
|
size_t len = strlen(pString) + 1; |
|
if ((pMemory = (char *)g_pMemAlloc->Alloc(len)) != NULL) |
|
{ |
|
return strcpy( pMemory, pString ); |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
inline wchar_t *MemAlloc_WcStrDup(const wchar_t *pString) |
|
{ |
|
wchar_t *pMemory; |
|
|
|
if (!pString) |
|
return NULL; |
|
|
|
size_t len = (wcslen(pString) + 1); |
|
if ((pMemory = (wchar_t *)g_pMemAlloc->Alloc(len * sizeof(wchar_t))) != NULL) |
|
{ |
|
return wcscpy( pMemory, pString ); |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
#endif // DBMEM_DEFINED_STRDUP |
|
|
|
#endif // USE_MEM_DEBUG |
|
|
|
#define MEMDBGON_H // Defined here so can be used above |
|
|
|
#else |
|
|
|
#if defined(USE_MEM_DEBUG) |
|
#ifndef _STATIC_LINKED |
|
#pragma message ("Note: file includes crtdbg.h directly, therefore will cannot use memdbgon.h in non-debug build") |
|
#else |
|
#error "Error: file includes crtdbg.h directly, therefore will cannot use memdbgon.h in non-debug build. Not recoverable in static build" |
|
#endif |
|
#endif |
|
#endif // _INC_CRTDBG |
|
|
|
#else |
|
|
|
// Needed for MEM_ALLOC_CREDIT(), MemAlloc_Alloc(), etc. |
|
|
|
#include "memalloc.h" |
|
|
|
#if !defined( VALVE_ALLOCS_DEFINED ) |
|
#define VALVE_ALLOCS_DEFINED |
|
|
|
#include "tier0/mem.h" |
|
|
|
inline void *valve_malloc_check_oom( size_t size ) |
|
{ |
|
void *ptr = malloc( size ); |
|
if ( !ptr ) |
|
MemAllocOOMError( size ); |
|
return ptr; |
|
} |
|
|
|
inline void *valve_realloc_check_oom( void *ptr, size_t size ) |
|
{ |
|
void *ret = realloc( ptr, size ); |
|
if ( !ret ) |
|
MemAllocOOMError( size ); |
|
return ret; |
|
} |
|
|
|
inline void *valve_calloc_check_oom( size_t num, size_t size ) |
|
{ |
|
void *ptr = calloc( num, size ); |
|
if (!ptr) |
|
MemAllocOOMError( num * size ); |
|
return ptr; |
|
} |
|
|
|
inline void *valve_memalign_check_oom( size_t alignment, size_t size ) |
|
{ |
|
void *ptr = memalign( alignment, size ); |
|
if (!ptr) |
|
MemAllocOOMError(size); |
|
return ptr; |
|
} |
|
|
|
inline void *valve_aligned_malloc_check_oom( size_t size, size_t alignment ) |
|
{ |
|
void *ptr = _aligned_malloc( size, alignment ); |
|
if (!ptr) |
|
MemAllocOOMError( size ); |
|
return ptr; |
|
} |
|
|
|
|
|
#endif // VALVE_ALLOCS_DEFINED |
|
|
|
#define malloc valve_malloc_check_oom |
|
#define realloc valve_realloc_check_oom |
|
#define calloc valve_calloc_check_oom |
|
#define memalign valve_memalign_check_oom |
|
#define _aligned_malloc valve_aligned_malloc_check_oom |
|
|
|
#endif // !STEAM && !NO_MALLOC_OVERRIDE |
|
|
|
#if defined( NO_MALLOC_OVERRIDE ) |
|
|
|
#undef malloc |
|
#undef realloc |
|
#undef calloc |
|
#undef memalign |
|
#undef _aligned_malloc |
|
|
|
#endif // NO_MALLOC_OVERRIDE
|
|
|