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.
1461 lines
34 KiB
1461 lines
34 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Insert this file into all projects using the memory system |
|
// It will cause that project to use the shader memory allocator |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
|
|
#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) |
|
|
|
#undef PROTECTED_THINGS_ENABLE // allow use of _vsnprintf |
|
|
|
#if defined( _WIN32 ) && !defined( _X360 ) |
|
#define WIN_32_LEAN_AND_MEAN |
|
#include <windows.h> |
|
#endif |
|
|
|
#ifdef _WIN32 |
|
// ARG: crtdbg is necessary for certain definitions below, |
|
// but it also redefines malloc as a macro in release. |
|
// To disable this, we gotta define _DEBUG before including it.. BLEAH! |
|
#define _DEBUG 1 |
|
#include "crtdbg.h" |
|
#ifdef NDEBUG |
|
#undef _DEBUG |
|
#endif |
|
// Turn this back off in release mode. |
|
#ifdef NDEBUG |
|
#undef _DEBUG |
|
#endif |
|
#endif |
|
|
|
#include "tier0/dbg.h" |
|
#include "tier0/memalloc.h" |
|
#include <string.h> |
|
#include <stdio.h> |
|
#include "memdbgoff.h" |
|
|
|
|
|
#if POSIX |
|
#define __cdecl |
|
#endif |
|
|
|
#if defined( _WIN32 ) && !defined( _X360 ) |
|
const char *MakeModuleFileName() |
|
{ |
|
if ( g_pMemAlloc && g_pMemAlloc->IsDebugHeap() ) |
|
{ |
|
char *pszModuleName = (char *)HeapAlloc( GetProcessHeap(), 0, MAX_PATH ); // small leak, debug only |
|
|
|
MEMORY_BASIC_INFORMATION mbi; |
|
static int dummy; |
|
VirtualQuery( &dummy, &mbi, sizeof(mbi) ); |
|
|
|
GetModuleFileName( reinterpret_cast<HMODULE>(mbi.AllocationBase), pszModuleName, MAX_PATH ); |
|
char *pDot = strrchr( pszModuleName, '.' ); |
|
if ( pDot ) |
|
{ |
|
char *pSlash = strrchr( pszModuleName, '\\' ); |
|
if ( pSlash ) |
|
{ |
|
pszModuleName = pSlash + 1; |
|
*pDot = 0; |
|
} |
|
} |
|
|
|
return pszModuleName; |
|
} |
|
return NULL; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: helper class to detect when static construction has been done by the CRT |
|
//----------------------------------------------------------------------------- |
|
class CStaticConstructionCheck |
|
{ |
|
public: |
|
volatile bool m_bConstructed = true; |
|
}; |
|
|
|
static CStaticConstructionCheck s_CheckStaticsConstructed; |
|
|
|
const char *GetModuleFileName() |
|
{ |
|
#if !defined(_MSC_VER) || ( _MSC_VER >= 1900 ) // VC 2015 and above, with the UCRT, will crash if you use a static before it is constructed |
|
if ( !s_CheckStaticsConstructed.m_bConstructed ) |
|
return nullptr; |
|
#endif |
|
|
|
static const char *pszOwner = MakeModuleFileName(); |
|
return pszOwner; |
|
} |
|
|
|
|
|
static void *AllocUnattributed( size_t nSize ) |
|
{ |
|
const char *pszOwner = GetModuleFileName(); |
|
|
|
if ( !pszOwner ) |
|
return g_pMemAlloc->Alloc(nSize); |
|
else |
|
return g_pMemAlloc->Alloc(nSize, pszOwner, 0); |
|
} |
|
|
|
static void *ReallocUnattributed( void *pMem, size_t nSize ) |
|
{ |
|
const char *pszOwner = GetModuleFileName(); |
|
|
|
if ( !pszOwner ) |
|
return g_pMemAlloc->Realloc(pMem, nSize); |
|
else |
|
return g_pMemAlloc->Realloc(pMem, nSize, pszOwner, 0); |
|
} |
|
|
|
#else |
|
#define MakeModuleFileName() NULL |
|
inline void *AllocUnattributed( size_t nSize ) |
|
{ |
|
return g_pMemAlloc->Alloc(nSize); |
|
} |
|
|
|
inline void *ReallocUnattributed( void *pMem, size_t nSize ) |
|
{ |
|
return g_pMemAlloc->Realloc(pMem, nSize); |
|
} |
|
#endif |
|
|
|
//----------------------------------------------------------------------------- |
|
// Standard functions in the CRT that we're going to override to call our allocator |
|
//----------------------------------------------------------------------------- |
|
#if defined(_WIN32) && !defined(_STATIC_LINKED) |
|
// this magic only works under win32 |
|
// under linux this malloc() overrides the libc malloc() and so we |
|
// end up in a recursion (as g_pMemAlloc->Alloc() calls malloc) |
|
#if _MSC_VER >= 1900 |
|
#define SUPPRESS_INVALID_PARAMETER_NO_INFO |
|
#define ALLOC_CALL __declspec(restrict) |
|
#define FREE_CALL |
|
#elif _MSC_VER >= 1400 |
|
#define ALLOC_CALL _CRTNOALIAS _CRTRESTRICT |
|
#define FREE_CALL _CRTNOALIAS |
|
#else |
|
#define ALLOC_CALL |
|
#define FREE_CALL |
|
#endif |
|
|
|
extern "C" |
|
{ |
|
|
|
ALLOC_CALL void *malloc( size_t nSize ) |
|
{ |
|
return AllocUnattributed( nSize ); |
|
} |
|
|
|
FREE_CALL void free( void *pMem ) |
|
{ |
|
g_pMemAlloc->Free(pMem); |
|
} |
|
|
|
ALLOC_CALL void *realloc( void *pMem, size_t nSize ) |
|
{ |
|
return ReallocUnattributed( pMem, nSize ); |
|
} |
|
|
|
ALLOC_CALL void *calloc( size_t nCount, size_t nElementSize ) |
|
{ |
|
void *pMem = AllocUnattributed( nElementSize * nCount ); |
|
memset(pMem, 0, nElementSize * nCount); |
|
return pMem; |
|
} |
|
|
|
} // end extern "C" |
|
|
|
//----------------------------------------------------------------------------- |
|
// Non-standard MSVC functions that we're going to override to call our allocator |
|
//----------------------------------------------------------------------------- |
|
extern "C" |
|
{ |
|
|
|
// 64-bit |
|
#ifdef _WIN64 |
|
void* __cdecl _malloc_base( size_t nSize ) |
|
{ |
|
return AllocUnattributed( nSize ); |
|
} |
|
#else |
|
ALLOC_CALL void *_malloc_base( size_t nSize ) |
|
{ |
|
return AllocUnattributed( nSize ); |
|
} |
|
#endif |
|
|
|
ALLOC_CALL void *_calloc_base( size_t nCount, size_t nSize ) |
|
{ |
|
void *pMem = AllocUnattributed( nSize*nCount ); |
|
memset(pMem, 0, nSize*nCount ); |
|
return pMem; |
|
} |
|
|
|
ALLOC_CALL void *_realloc_base( void *pMem, size_t nSize ) |
|
{ |
|
return ReallocUnattributed( pMem, nSize ); |
|
} |
|
|
|
ALLOC_CALL void *_recalloc_base( void *pMem, size_t nSize ) |
|
{ |
|
void *pMemOut = ReallocUnattributed( pMem, nSize ); |
|
if ( !pMem ) |
|
{ |
|
memset( pMemOut, 0, nSize ); |
|
} |
|
return pMemOut; |
|
} |
|
|
|
void _free_base( void *pMem ) |
|
{ |
|
g_pMemAlloc->Free(pMem); |
|
} |
|
|
|
void *__cdecl _expand_base( void *pMem, size_t nNewSize, int nBlockUse ) |
|
{ |
|
Assert( 0 ); |
|
return NULL; |
|
} |
|
|
|
// crt |
|
void * __cdecl _malloc_crt(size_t size) |
|
{ |
|
return AllocUnattributed( size ); |
|
} |
|
|
|
void * __cdecl _calloc_crt(size_t count, size_t size) |
|
{ |
|
return _calloc_base( count, size ); |
|
} |
|
|
|
void * __cdecl _realloc_crt(void *ptr, size_t size) |
|
{ |
|
return _realloc_base( ptr, size ); |
|
} |
|
|
|
void * __cdecl _recalloc_crt(void *ptr, size_t count, size_t size) |
|
{ |
|
return _recalloc_base( ptr, size * count ); |
|
} |
|
|
|
ALLOC_CALL void * __cdecl _recalloc ( void * memblock, size_t count, size_t size ) |
|
{ |
|
void *pMem = ReallocUnattributed( memblock, size * count ); |
|
if ( !memblock ) |
|
{ |
|
memset( pMem, 0, size * count ); |
|
} |
|
return pMem; |
|
} |
|
|
|
size_t _msize_base( void *pMem ) |
|
{ |
|
return g_pMemAlloc->GetSize(pMem); |
|
} |
|
|
|
size_t _msize( void *pMem ) |
|
{ |
|
return _msize_base(pMem); |
|
} |
|
|
|
size_t msize( void *pMem ) |
|
{ |
|
return g_pMemAlloc->GetSize(pMem); |
|
} |
|
|
|
void *__cdecl _heap_alloc( size_t nSize ) |
|
{ |
|
return AllocUnattributed( nSize ); |
|
} |
|
|
|
void *__cdecl _nh_malloc( size_t nSize, int ) |
|
{ |
|
return AllocUnattributed( nSize ); |
|
} |
|
|
|
void *__cdecl _expand( void *pMem, size_t nSize ) |
|
{ |
|
Assert( 0 ); |
|
return NULL; |
|
} |
|
|
|
unsigned int _amblksiz = 16; //BYTES_PER_PARA; |
|
|
|
#if _MSC_VER >= 1400 |
|
HANDLE _crtheap = (HANDLE)1; // PatM Can't be 0 or CRT pukes |
|
int __active_heap = 1; |
|
#endif // _MSC_VER >= 1400 |
|
|
|
size_t __cdecl _get_sbh_threshold( void ) |
|
{ |
|
return 0; |
|
} |
|
|
|
int __cdecl _set_sbh_threshold( size_t ) |
|
{ |
|
return 0; |
|
} |
|
|
|
int _heapchk() |
|
{ |
|
return g_pMemAlloc->heapchk(); |
|
} |
|
|
|
int _heapmin() |
|
{ |
|
return 1; |
|
} |
|
|
|
int __cdecl _heapadd( void *, size_t ) |
|
{ |
|
return 0; |
|
} |
|
|
|
int __cdecl _heapset( unsigned int ) |
|
{ |
|
return 0; |
|
} |
|
|
|
size_t __cdecl _heapused( size_t *, size_t * ) |
|
{ |
|
return 0; |
|
} |
|
|
|
#ifdef _WIN32 |
|
int __cdecl _heapwalk( _HEAPINFO * ) |
|
{ |
|
return 0; |
|
} |
|
#endif |
|
|
|
} // end extern "C" |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Debugging functions that we're going to override to call our allocator |
|
// NOTE: These have to be here for release + debug builds in case we |
|
// link to a debug static lib!!! |
|
//----------------------------------------------------------------------------- |
|
|
|
extern "C" |
|
{ |
|
|
|
void *malloc_db( size_t nSize, const char *pFileName, int nLine ) |
|
{ |
|
return g_pMemAlloc->Alloc(nSize, pFileName, nLine); |
|
} |
|
|
|
void free_db( void *pMem, const char *pFileName, int nLine ) |
|
{ |
|
g_pMemAlloc->Free(pMem, pFileName, nLine); |
|
} |
|
|
|
void *realloc_db( void *pMem, size_t nSize, const char *pFileName, int nLine ) |
|
{ |
|
return g_pMemAlloc->Realloc(pMem, nSize, pFileName, nLine); |
|
} |
|
|
|
} // end extern "C" |
|
|
|
//----------------------------------------------------------------------------- |
|
// These methods are standard MSVC heap initialization + shutdown methods |
|
//----------------------------------------------------------------------------- |
|
extern "C" |
|
{ |
|
|
|
#if !defined( _X360 ) |
|
int __cdecl _heap_init() |
|
{ |
|
return g_pMemAlloc != NULL; |
|
} |
|
|
|
void __cdecl _heap_term() |
|
{ |
|
} |
|
#endif |
|
|
|
} |
|
#endif |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Prevents us from using an inappropriate new or delete method, |
|
// ensures they are here even when linking against debug or release static libs |
|
//----------------------------------------------------------------------------- |
|
#ifndef NO_MEMOVERRIDE_NEW_DELETE |
|
#if defined (OSX) || defined (ANDROID) |
|
void *__cdecl operator new( size_t nSize ) throw (std::bad_alloc) |
|
#else |
|
void *__cdecl operator new( size_t nSize ) |
|
#endif |
|
{ |
|
return AllocUnattributed( nSize ); |
|
} |
|
|
|
void *__cdecl operator new( size_t nSize, int nBlockUse, const char *pFileName, int nLine ) |
|
{ |
|
return g_pMemAlloc->Alloc(nSize, pFileName, nLine); |
|
} |
|
|
|
#if defined (OSX) || defined (ANDROID) |
|
void __cdecl operator delete( void *pMem ) throw() |
|
#else |
|
void __cdecl operator delete( void *pMem ) |
|
#endif |
|
{ |
|
g_pMemAlloc->Free( pMem ); |
|
} |
|
#if defined (OSX) || defined (ANDROID) |
|
void operator delete(void*pMem, std::size_t) |
|
#else |
|
void operator delete(void*pMem, std::size_t) throw() |
|
#endif |
|
{ |
|
g_pMemAlloc->Free( pMem ); |
|
} |
|
|
|
#if defined (OSX) || defined (ANDROID) |
|
void *__cdecl operator new[]( size_t nSize ) throw (std::bad_alloc) |
|
#else |
|
void *__cdecl operator new[]( size_t nSize ) |
|
#endif |
|
{ |
|
return AllocUnattributed( nSize ); |
|
} |
|
|
|
void *__cdecl operator new[] ( size_t nSize, int nBlockUse, const char *pFileName, int nLine ) |
|
{ |
|
return g_pMemAlloc->Alloc(nSize, pFileName, nLine); |
|
} |
|
|
|
#if defined (OSX) || defined (ANDROID) |
|
void __cdecl operator delete[]( void *pMem ) throw() |
|
#else |
|
void __cdecl operator delete[]( void *pMem ) |
|
#endif |
|
{ |
|
g_pMemAlloc->Free( pMem ); |
|
} |
|
#endif |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Override some debugging allocation methods in MSVC |
|
// NOTE: These have to be here for release + debug builds in case we |
|
// link to a debug static lib!!! |
|
//----------------------------------------------------------------------------- |
|
#ifndef _STATIC_LINKED |
|
#ifdef _WIN32 |
|
|
|
// This here just hides the internal file names, etc of allocations |
|
// made in the c runtime library |
|
#define CRT_INTERNAL_FILE_NAME "C-runtime internal" |
|
|
|
class CAttibCRT |
|
{ |
|
public: |
|
CAttibCRT(int nBlockUse) : m_nBlockUse(nBlockUse) |
|
{ |
|
if (m_nBlockUse == _CRT_BLOCK) |
|
{ |
|
g_pMemAlloc->PushAllocDbgInfo(CRT_INTERNAL_FILE_NAME, 0); |
|
} |
|
} |
|
|
|
~CAttibCRT() |
|
{ |
|
if (m_nBlockUse == _CRT_BLOCK) |
|
{ |
|
g_pMemAlloc->PopAllocDbgInfo(); |
|
} |
|
} |
|
|
|
private: |
|
int m_nBlockUse; |
|
}; |
|
|
|
|
|
#define AttribIfCrt() CAttibCRT _attrib(nBlockUse) |
|
#elif defined(POSIX) |
|
#define AttribIfCrt() |
|
#endif // _WIN32 |
|
|
|
|
|
extern "C" |
|
{ |
|
|
|
void *__cdecl _nh_malloc_dbg( size_t nSize, int nFlag, int nBlockUse, |
|
const char *pFileName, int nLine ) |
|
{ |
|
AttribIfCrt(); |
|
return g_pMemAlloc->Alloc(nSize, pFileName, nLine); |
|
} |
|
|
|
void *__cdecl _malloc_dbg( size_t nSize, int nBlockUse, |
|
const char *pFileName, int nLine ) |
|
{ |
|
AttribIfCrt(); |
|
return g_pMemAlloc->Alloc(nSize, pFileName, nLine); |
|
} |
|
|
|
#if defined( _X360 ) |
|
void *__cdecl _calloc_dbg_impl( size_t nNum, size_t nSize, int nBlockUse, |
|
const char * szFileName, int nLine, int * errno_tmp ) |
|
{ |
|
return _calloc_dbg( nNum, nSize, nBlockUse, szFileName, nLine ); |
|
} |
|
#endif |
|
|
|
void *__cdecl _calloc_dbg( size_t nNum, size_t nSize, int nBlockUse, |
|
const char *pFileName, int nLine ) |
|
{ |
|
AttribIfCrt(); |
|
void *pMem = g_pMemAlloc->Alloc(nSize * nNum, pFileName, nLine); |
|
memset(pMem, 0, nSize * nNum); |
|
return pMem; |
|
} |
|
|
|
void *__cdecl _calloc_dbg_impl( size_t nNum, size_t nSize, int nBlockUse, |
|
const char * szFileName, int nLine, int * errno_tmp ) |
|
{ |
|
return _calloc_dbg( nNum, nSize, nBlockUse, szFileName, nLine ); |
|
} |
|
|
|
void *__cdecl _realloc_dbg( void *pMem, size_t nNewSize, int nBlockUse, |
|
const char *pFileName, int nLine ) |
|
{ |
|
AttribIfCrt(); |
|
return g_pMemAlloc->Realloc(pMem, nNewSize, pFileName, nLine); |
|
} |
|
|
|
void *__cdecl _expand_dbg( void *pMem, size_t nNewSize, int nBlockUse, |
|
const char *pFileName, int nLine ) |
|
{ |
|
Assert( 0 ); |
|
return NULL; |
|
} |
|
|
|
void __cdecl _free_dbg( void *pMem, int nBlockUse ) |
|
{ |
|
AttribIfCrt(); |
|
g_pMemAlloc->Free(pMem); |
|
} |
|
|
|
size_t __cdecl _msize_dbg( void *pMem, int nBlockUse ) |
|
{ |
|
#ifdef _WIN32 |
|
return _msize(pMem); |
|
#elif POSIX |
|
Assert( "_msize_dbg unsupported" ); |
|
return 0; |
|
#endif |
|
} |
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
#if defined(_DEBUG) && _MSC_VER >= 1300 |
|
// aligned base |
|
ALLOC_CALL void *__cdecl _aligned_malloc_base( size_t size, size_t align ) |
|
{ |
|
return MemAlloc_AllocAligned( size, align ); |
|
} |
|
|
|
inline void *MemAlloc_Unalign( void *pMemBlock ) |
|
{ |
|
unsigned *pAlloc = (unsigned *)pMemBlock; |
|
|
|
// pAlloc points to the pointer to starting of the memory block |
|
pAlloc = (unsigned *)(((size_t)pAlloc & ~(sizeof( void * ) - 1)) - sizeof( void * )); |
|
|
|
// pAlloc is the pointer to the start of memory block |
|
return *((unsigned **)pAlloc); |
|
} |
|
|
|
ALLOC_CALL void *__cdecl _aligned_realloc_base( void *ptr, size_t size, size_t align ) |
|
{ |
|
if ( ptr && !size ) |
|
{ |
|
MemAlloc_FreeAligned( ptr ); |
|
return NULL; |
|
} |
|
|
|
void *pNew = MemAlloc_AllocAligned( size, align ); |
|
if ( ptr ) |
|
{ |
|
void *ptrUnaligned = MemAlloc_Unalign( ptr ); |
|
size_t oldSize = g_pMemAlloc->GetSize( ptrUnaligned ); |
|
size_t oldOffset = (uintp)ptr - (uintp)ptrUnaligned; |
|
size_t copySize = oldSize - oldOffset; |
|
if ( copySize > size ) |
|
copySize = size; |
|
memcpy( pNew, ptr, copySize ); |
|
MemAlloc_FreeAligned( ptr ); |
|
} |
|
return pNew; |
|
} |
|
|
|
ALLOC_CALL void *__cdecl _aligned_recalloc_base( void *ptr, size_t size, size_t align ) |
|
{ |
|
Error( "Unsupported function\n" ); |
|
return NULL; |
|
} |
|
|
|
FREE_CALL void __cdecl _aligned_free_base( void *ptr ) |
|
{ |
|
MemAlloc_FreeAligned( ptr ); |
|
} |
|
|
|
// aligned |
|
ALLOC_CALL void * __cdecl _aligned_malloc( size_t size, size_t align ) |
|
{ |
|
return _aligned_malloc_base(size, align); |
|
} |
|
|
|
ALLOC_CALL void *__cdecl _aligned_realloc(void *memblock, size_t size, size_t align) |
|
{ |
|
return _aligned_realloc_base(memblock, size, align); |
|
} |
|
|
|
ALLOC_CALL void * __cdecl _aligned_recalloc( void * memblock, size_t count, size_t size, size_t align ) |
|
{ |
|
return _aligned_recalloc_base(memblock, count * size, align); |
|
} |
|
|
|
FREE_CALL void __cdecl _aligned_free( void *memblock ) |
|
{ |
|
_aligned_free_base(memblock); |
|
} |
|
|
|
// aligned offset base |
|
ALLOC_CALL void * __cdecl _aligned_offset_malloc_base( size_t size, size_t align, size_t offset ) |
|
{ |
|
Assert( IsPC() || 0 ); |
|
return NULL; |
|
} |
|
|
|
ALLOC_CALL void * __cdecl _aligned_offset_realloc_base( void * memblock, size_t size, size_t align, size_t offset) |
|
{ |
|
Assert( IsPC() || 0 ); |
|
return NULL; |
|
} |
|
|
|
ALLOC_CALL void * __cdecl _aligned_offset_recalloc_base( void * memblock, size_t size, size_t align, size_t offset) |
|
{ |
|
Assert( IsPC() || 0 ); |
|
return NULL; |
|
} |
|
|
|
// aligned offset |
|
ALLOC_CALL void *__cdecl _aligned_offset_malloc(size_t size, size_t align, size_t offset) |
|
{ |
|
return _aligned_offset_malloc_base( size, align, offset ); |
|
} |
|
|
|
ALLOC_CALL void *__cdecl _aligned_offset_realloc(void *memblock, size_t size, size_t align, size_t offset) |
|
{ |
|
return _aligned_offset_realloc_base( memblock, size, align, offset ); |
|
} |
|
|
|
ALLOC_CALL void * __cdecl _aligned_offset_recalloc( void * memblock, size_t count, size_t size, size_t align, size_t offset ) |
|
{ |
|
return _aligned_offset_recalloc_base( memblock, count * size, align, offset ); |
|
} |
|
|
|
#endif // _MSC_VER >= 1400 |
|
|
|
#endif |
|
|
|
} // end extern "C" |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Override some the _CRT debugging allocation methods in MSVC |
|
//----------------------------------------------------------------------------- |
|
#ifdef _WIN32 |
|
|
|
extern "C" |
|
{ |
|
|
|
int _CrtDumpMemoryLeaks(void) |
|
{ |
|
return 0; |
|
} |
|
|
|
_CRT_DUMP_CLIENT _CrtSetDumpClient( _CRT_DUMP_CLIENT dumpClient ) |
|
{ |
|
return NULL; |
|
} |
|
|
|
int _CrtSetDbgFlag( int nNewFlag ) |
|
{ |
|
return g_pMemAlloc->CrtSetDbgFlag( nNewFlag ); |
|
} |
|
|
|
// 64-bit port. |
|
#define AFNAME(var) __p_##var |
|
#define AFRET(var) &var |
|
#if defined(_crtDbgFlag) |
|
#undef _crtDbgFlag |
|
#endif |
|
#if defined(_crtBreakAlloc) |
|
#undef _crtBreakAlloc |
|
#endif |
|
|
|
int _crtDbgFlag = _CRTDBG_ALLOC_MEM_DF; |
|
int* AFNAME(_crtDbgFlag)(void) |
|
{ |
|
return AFRET(_crtDbgFlag); |
|
} |
|
|
|
long _crtBreakAlloc; /* Break on this allocation */ |
|
long* AFNAME(_crtBreakAlloc) (void) |
|
{ |
|
return AFRET(_crtBreakAlloc); |
|
} |
|
|
|
void __cdecl _CrtSetDbgBlockType( void *pMem, int nBlockUse ) |
|
{ |
|
DebuggerBreak(); |
|
} |
|
|
|
_CRT_ALLOC_HOOK __cdecl _CrtSetAllocHook( _CRT_ALLOC_HOOK pfnNewHook ) |
|
{ |
|
DebuggerBreak(); |
|
return NULL; |
|
} |
|
|
|
long __cdecl _CrtSetBreakAlloc( long lNewBreakAlloc ) |
|
{ |
|
return g_pMemAlloc->CrtSetBreakAlloc( lNewBreakAlloc ); |
|
} |
|
|
|
int __cdecl _CrtIsValidHeapPointer( const void *pMem ) |
|
{ |
|
return g_pMemAlloc->CrtIsValidHeapPointer( pMem ); |
|
} |
|
|
|
int __cdecl _CrtIsValidPointer( const void *pMem, unsigned int size, int access ) |
|
{ |
|
return g_pMemAlloc->CrtIsValidPointer( pMem, size, access ); |
|
} |
|
|
|
int __cdecl _CrtCheckMemory( void ) |
|
{ |
|
// FIXME: Remove this when we re-implement the heap |
|
return g_pMemAlloc->CrtCheckMemory( ); |
|
} |
|
|
|
int __cdecl _CrtIsMemoryBlock( const void *pMem, unsigned int nSize, |
|
long *plRequestNumber, char **ppFileName, int *pnLine ) |
|
{ |
|
DebuggerBreak(); |
|
return 1; |
|
} |
|
|
|
int __cdecl _CrtMemDifference( _CrtMemState *pState, const _CrtMemState * oldState, const _CrtMemState * newState ) |
|
{ |
|
DebuggerBreak(); |
|
return FALSE; |
|
} |
|
|
|
void __cdecl _CrtMemDumpStatistics( const _CrtMemState *pState ) |
|
{ |
|
DebuggerBreak(); |
|
} |
|
|
|
void __cdecl _CrtMemCheckpoint( _CrtMemState *pState ) |
|
{ |
|
// FIXME: Remove this when we re-implement the heap |
|
g_pMemAlloc->CrtMemCheckpoint( pState ); |
|
} |
|
|
|
void __cdecl _CrtMemDumpAllObjectsSince( const _CrtMemState *pState ) |
|
{ |
|
DebuggerBreak(); |
|
} |
|
|
|
void __cdecl _CrtDoForAllClientObjects( void (*pfn)(void *, void *), void * pContext ) |
|
{ |
|
DebuggerBreak(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Methods in dbgrpt.cpp |
|
//----------------------------------------------------------------------------- |
|
long _crtAssertBusy = -1; |
|
|
|
int __cdecl _CrtSetReportMode( int nReportType, int nReportMode ) |
|
{ |
|
return g_pMemAlloc->CrtSetReportMode( nReportType, nReportMode ); |
|
} |
|
|
|
_HFILE __cdecl _CrtSetReportFile( int nRptType, _HFILE hFile ) |
|
{ |
|
return (_HFILE)g_pMemAlloc->CrtSetReportFile( nRptType, hFile ); |
|
} |
|
|
|
_CRT_REPORT_HOOK __cdecl _CrtSetReportHook( _CRT_REPORT_HOOK pfnNewHook ) |
|
{ |
|
return (_CRT_REPORT_HOOK)g_pMemAlloc->CrtSetReportHook( pfnNewHook ); |
|
} |
|
|
|
int __cdecl _CrtDbgReport( int nRptType, const char * szFile, |
|
int nLine, const char * szModule, const char * szFormat, ... ) |
|
{ |
|
static char output[1024]; |
|
va_list args; |
|
if ( szFormat ) |
|
{ |
|
va_start( args, szFormat ); |
|
_vsnprintf( output, sizeof( output )-1, szFormat, args ); |
|
va_end( args ); |
|
} |
|
else |
|
{ |
|
output[0] = 0; |
|
} |
|
|
|
return g_pMemAlloc->CrtDbgReport( nRptType, szFile, nLine, szModule, output ); |
|
} |
|
|
|
#if _MSC_VER >= 1400 |
|
|
|
// Configure VS so that it will record crash dumps on pure-call violations |
|
// and invalid parameter handlers. |
|
// If you manage to call a pure-virtual function (easily done if you indirectly |
|
// call a pure-virtual function from the base-class constructor or destructor) |
|
// or if you invoke the invalid parameter handler (printf(NULL); is one way) |
|
// then no crash dump will be created. |
|
// This crash redirects the handlers for these two events so that crash dumps |
|
// are created. |
|
// |
|
// The ErrorHandlerRegistrar object must be in memoverride.cpp so that it will |
|
// be placed in every DLL and EXE. This is required because each DLL and EXE |
|
// gets its own copy of the C run-time and these overrides are set on a per-CRT |
|
// basis. |
|
|
|
/* |
|
// This sample code will cause pure-call and invalid_parameter violations and |
|
// was used for testing: |
|
class Base |
|
{ |
|
public: |
|
virtual void PureFunction() = 0; |
|
|
|
Base() |
|
{ |
|
NonPureFunction(); |
|
} |
|
|
|
void NonPureFunction() |
|
{ |
|
PureFunction(); |
|
} |
|
}; |
|
|
|
class Derived : public Base |
|
{ |
|
public: |
|
void PureFunction() OVERRIDE |
|
{ |
|
} |
|
}; |
|
|
|
void PureCallViolation() |
|
{ |
|
Derived derived; |
|
} |
|
|
|
void InvalidParameterViolation() |
|
{ |
|
printf( NULL ); |
|
} |
|
*/ |
|
|
|
#include <stdlib.h> |
|
#include "minidump.h" |
|
|
|
// Disable compiler optimizations. If we don't do this then VC++ generates code |
|
// that confuses the Visual Studio debugger and causes it to display completely |
|
// random call stacks. That makes the minidumps excruciatingly hard to understand. |
|
#pragma optimize("", off) |
|
|
|
// Write a minidump file, unless running under the debugger in which case break |
|
// into the debugger. |
|
// The "int dummy" parameter is so that the callers can be unique so that the |
|
// linker won't use its /opt:icf optimization to collapse them together. This |
|
// makes reading the call stack easier. |
|
void __cdecl WriteMiniDumpOrBreak( int dummy, const char *pchName ) |
|
{ |
|
if ( Plat_IsInDebugSession() ) |
|
{ |
|
__debugbreak(); |
|
// Continue at your peril... |
|
} |
|
else |
|
{ |
|
WriteMiniDump( pchName ); |
|
// Call Plat_ExitProcess so we don't continue in a bad state. |
|
TerminateProcess(GetCurrentProcess(), 0); |
|
} |
|
} |
|
|
|
void __cdecl VPureCall() |
|
{ |
|
WriteMiniDumpOrBreak( 0, "PureClass" ); |
|
} |
|
|
|
void VInvalidParameterHandler(const wchar_t* expression, |
|
const wchar_t* function, |
|
const wchar_t* file, |
|
unsigned int line, |
|
uintptr_t pReserved) |
|
{ |
|
WriteMiniDumpOrBreak( 1, "InvalidParameterHandler" ); |
|
} |
|
|
|
// Restore compiler optimizations. |
|
#pragma optimize("", on) |
|
|
|
// Helper class for registering error callbacks. See above for details. |
|
class ErrorHandlerRegistrar |
|
{ |
|
public: |
|
ErrorHandlerRegistrar(); |
|
} s_ErrorHandlerRegistration; |
|
|
|
ErrorHandlerRegistrar::ErrorHandlerRegistrar() |
|
{ |
|
_set_purecall_handler( VPureCall ); |
|
_set_invalid_parameter_handler( VInvalidParameterHandler ); |
|
} |
|
|
|
#if defined( _DEBUG ) |
|
|
|
// wrapper which passes no debug info; not available in debug |
|
#ifndef SUPPRESS_INVALID_PARAMETER_NO_INFO |
|
void __cdecl _invalid_parameter_noinfo(void) |
|
{ |
|
Assert(0); |
|
} |
|
#endif |
|
|
|
#endif /* defined( _DEBUG ) */ |
|
|
|
#if defined( _DEBUG ) || defined( USE_MEM_DEBUG ) |
|
|
|
int __cdecl __crtMessageWindowW( int nRptType, const wchar_t * szFile, const wchar_t * szLine, |
|
const wchar_t * szModule, const wchar_t * szUserMessage ) |
|
{ |
|
Assert(0); |
|
return 0; |
|
} |
|
|
|
int __cdecl _CrtDbgReportV( int nRptType, const wchar_t *szFile, int nLine, |
|
const wchar_t *szModule, const wchar_t *szFormat, va_list arglist ) |
|
{ |
|
Assert(0); |
|
return 0; |
|
} |
|
|
|
int __cdecl _CrtDbgReportW( int nRptType, const wchar_t *szFile, int nLine, |
|
const wchar_t *szModule, const wchar_t *szFormat, ...) |
|
{ |
|
Assert(0); |
|
return 0; |
|
} |
|
|
|
#if _MSC_VER >= 1900 |
|
int __cdecl _VCrtDbgReportA( int nRptType, void* ReturnAddress, const char * szFile, int nLine, |
|
const char * szModule, const char * szFormat, va_list arglist ) |
|
{ |
|
Assert(0); |
|
return 0; |
|
} |
|
#else |
|
int __cdecl _VCrtDbgReportA( int nRptType, const wchar_t * szFile, int nLine, |
|
const wchar_t * szModule, const wchar_t * szFormat, va_list arglist ) |
|
{ |
|
Assert( 0 ); |
|
return 0; |
|
} |
|
#endif |
|
|
|
int __cdecl _CrtSetReportHook2( int mode, _CRT_REPORT_HOOK pfnNewHook ) |
|
{ |
|
_CrtSetReportHook( pfnNewHook ); |
|
return 0; |
|
} |
|
|
|
|
|
#endif /* defined( _DEBUG ) || defined( USE_MEM_DEBUG ) */ |
|
|
|
extern "C" int __crtDebugCheckCount = FALSE; |
|
|
|
extern "C" int __cdecl _CrtSetCheckCount( int fCheckCount ) |
|
{ |
|
int oldCheckCount = __crtDebugCheckCount; |
|
return oldCheckCount; |
|
} |
|
|
|
extern "C" int __cdecl _CrtGetCheckCount( void ) |
|
{ |
|
return __crtDebugCheckCount; |
|
} |
|
|
|
// aligned offset debug |
|
extern "C" void * __cdecl _aligned_offset_recalloc_dbg( void * memblock, size_t count, size_t size, size_t align, size_t offset, const char * f_name, int line_n ) |
|
{ |
|
Assert( IsPC() || 0 ); |
|
void *pMem = ReallocUnattributed( memblock, size * count ); |
|
if ( !memblock ) |
|
{ |
|
memset( pMem, 0, size * count ); |
|
} |
|
return pMem; |
|
} |
|
|
|
extern "C" void * __cdecl _aligned_recalloc_dbg( void *memblock, size_t count, size_t size, size_t align, const char * f_name, int line_n ) |
|
{ |
|
return _aligned_offset_recalloc_dbg(memblock, count, size, align, 0, f_name, line_n); |
|
} |
|
|
|
extern "C" void * __cdecl _recalloc_dbg ( void * memblock, size_t count, size_t size, int nBlockUse, const char * szFileName, int nLine ) |
|
{ |
|
return _aligned_offset_recalloc_dbg(memblock, count, size, 0, 0, szFileName, nLine); |
|
} |
|
|
|
_CRT_REPORT_HOOK __cdecl _CrtGetReportHook( void ) |
|
{ |
|
return NULL; |
|
} |
|
|
|
#endif |
|
int __cdecl _CrtReportBlockType(const void * pUserData) |
|
{ |
|
return 0; |
|
} |
|
|
|
|
|
} // end extern "C" |
|
#endif // _WIN32 |
|
|
|
// Most files include this file, so when it's used it adds an extra .ValveDbg section, |
|
// to help identify debug binaries. |
|
#ifdef _WIN32 |
|
#ifndef NDEBUG // _DEBUG |
|
#pragma data_seg("ValveDBG") |
|
volatile const char* DBG = "*** DEBUG STUB ***"; |
|
#endif |
|
#endif |
|
|
|
#endif |
|
|
|
// Extras added prevent dbgheap.obj from being included - DAL |
|
#ifdef _WIN32 |
|
|
|
extern "C" |
|
{ |
|
size_t __crtDebugFillThreshold = 0; |
|
|
|
extern "C" void * __cdecl _heap_alloc_base (size_t size) { |
|
assert(0); |
|
return NULL; |
|
} |
|
|
|
|
|
void * __cdecl _heap_alloc_dbg( size_t nSize, int nBlockUse, const char * szFileName, int nLine) |
|
{ |
|
return _heap_alloc(nSize); |
|
} |
|
|
|
// 64-bit |
|
#ifdef _WIN64 |
|
static void * __cdecl realloc_help( void * pUserData, size_t * pnNewSize, int nBlockUse,const char * szFileName, |
|
int nLine, int fRealloc ) |
|
{ |
|
assert(0); // Shouldn't be needed |
|
return NULL; |
|
} |
|
#else |
|
static void * __cdecl realloc_help( void * pUserData, size_t nNewSize, int nBlockUse, const char * szFileName, |
|
int nLine, int fRealloc) |
|
{ |
|
assert(0); // Shouldn't be needed |
|
return NULL; |
|
} |
|
#endif |
|
|
|
void __cdecl _free_nolock( void * pUserData) |
|
{ |
|
// I don't think the second param is used in memoverride |
|
_free_dbg(pUserData, 0); |
|
} |
|
|
|
void __cdecl _free_dbg_nolock( void * pUserData, int nBlockUse) |
|
{ |
|
_free_dbg(pUserData, 0); |
|
} |
|
|
|
_CRT_ALLOC_HOOK __cdecl _CrtGetAllocHook ( void) |
|
{ |
|
assert(0); |
|
return NULL; |
|
} |
|
|
|
static int __cdecl CheckBytes( unsigned char * pb, unsigned char bCheck, size_t nSize) |
|
{ |
|
int bOkay = TRUE; |
|
return bOkay; |
|
} |
|
|
|
|
|
_CRT_DUMP_CLIENT __cdecl _CrtGetDumpClient ( void) |
|
{ |
|
assert(0); |
|
return NULL; |
|
} |
|
|
|
#if _MSC_VER >= 1400 |
|
static void __cdecl _printMemBlockData( _locale_t plocinfo, _CrtMemBlockHeader * pHead) |
|
{ |
|
} |
|
|
|
static void __cdecl _CrtMemDumpAllObjectsSince_stat( const _CrtMemState * state, _locale_t plocinfo) |
|
{ |
|
} |
|
#endif |
|
void * __cdecl _aligned_malloc_dbg( size_t size, size_t align, const char * f_name, int line_n) |
|
{ |
|
return _aligned_malloc(size, align); |
|
} |
|
|
|
void * __cdecl _aligned_realloc_dbg( void *memblock, size_t size, size_t align, |
|
const char * f_name, int line_n) |
|
{ |
|
return _aligned_realloc(memblock, size, align); |
|
} |
|
|
|
void * __cdecl _aligned_offset_malloc_dbg( size_t size, size_t align, size_t offset, |
|
const char * f_name, int line_n) |
|
{ |
|
return _aligned_offset_malloc(size, align, offset); |
|
} |
|
|
|
void * __cdecl _aligned_offset_realloc_dbg( void * memblock, size_t size, size_t align, |
|
size_t offset, const char * f_name, int line_n) |
|
{ |
|
return _aligned_offset_realloc(memblock, size, align, offset); |
|
} |
|
|
|
void __cdecl _aligned_free_dbg( void * memblock) |
|
{ |
|
_aligned_free(memblock); |
|
} |
|
|
|
#if _MSC_VER < 1900 |
|
size_t __cdecl _CrtSetDebugFillThreshold( size_t _NewDebugFillThreshold) |
|
{ |
|
assert(0); |
|
return 0; |
|
} |
|
|
|
//=========================================== |
|
// NEW!!! 64-bit |
|
|
|
char * __cdecl _strdup ( const char * string ) |
|
{ |
|
int nSize = (int)strlen(string) + 1; |
|
// Check for integer underflow. |
|
if ( nSize <= 0 ) |
|
return NULL; |
|
char *pCopy = (char*)AllocUnattributed( nSize ); |
|
if ( pCopy ) |
|
memcpy( pCopy, string, nSize ); |
|
return pCopy; |
|
} |
|
#endif |
|
|
|
#if 0 |
|
_TSCHAR * __cdecl _tfullpath_dbg ( _TSCHAR *UserBuf, const _TSCHAR *path, size_t maxlen, int nBlockUse, const char * szFileName, int nLine ) |
|
{ |
|
Assert(0); |
|
return NULL; |
|
} |
|
|
|
_TSCHAR * __cdecl _tfullpath ( _TSCHAR *UserBuf, const _TSCHAR *path, size_t maxlen ) |
|
{ |
|
Assert(0); |
|
return NULL; |
|
} |
|
|
|
_TSCHAR * __cdecl _tgetdcwd_lk_dbg ( int drive, _TSCHAR *pnbuf, int maxlen, int nBlockUse, const char * szFileName, int nLine ) |
|
{ |
|
Assert(0); |
|
return NULL; |
|
} |
|
|
|
_TSCHAR * __cdecl _tgetdcwd_nolock ( int drive, _TSCHAR *pnbuf, int maxlen ) |
|
{ |
|
Assert(0); |
|
return NULL; |
|
} |
|
|
|
errno_t __cdecl _tdupenv_s_helper ( _TSCHAR **pBuffer, size_t *pBufferSizeInTChars, const _TSCHAR *varname, int nBlockUse, const char * szFileName, int nLine ) |
|
{ |
|
Assert(0); |
|
return 0; |
|
} |
|
|
|
errno_t __cdecl _tdupenv_s_helper ( _TSCHAR **pBuffer, size_t *pBufferSizeInTChars, const _TSCHAR *varname ) |
|
{ |
|
Assert(0); |
|
return 0; |
|
} |
|
|
|
_TSCHAR * __cdecl _ttempnam_dbg ( const _TSCHAR *dir, const _TSCHAR *pfx, int nBlockUse, const char * szFileName, int nLine ) |
|
{ |
|
Assert(0); |
|
return 0; |
|
} |
|
|
|
_TSCHAR * __cdecl _ttempnam ( const _TSCHAR *dir, const _TSCHAR *pfx ) |
|
{ |
|
Assert(0); |
|
return 0; |
|
} |
|
|
|
wchar_t * __cdecl _wcsdup_dbg ( const wchar_t * string, int nBlockUse, const char * szFileName, int nLine ) |
|
{ |
|
Assert(0); |
|
return 0; |
|
} |
|
|
|
wchar_t * __cdecl _wcsdup ( const wchar_t * string ) |
|
{ |
|
Assert(0); |
|
return 0; |
|
} |
|
#endif |
|
} // end extern "C" |
|
|
|
#if _MSC_VER >= 1400 |
|
|
|
//----------------------------------------------------------------------------- |
|
// XBox Memory Allocator Override |
|
//----------------------------------------------------------------------------- |
|
#if defined( _X360 ) |
|
#if defined( _DEBUG ) || defined( USE_MEM_DEBUG ) |
|
#include "utlmap.h" |
|
|
|
MEMALLOC_DEFINE_EXTERNAL_TRACKING( XMem ); |
|
|
|
CThreadFastMutex g_XMemAllocMutex; |
|
|
|
void XMemAlloc_RegisterAllocation( void *p, DWORD dwAllocAttributes ) |
|
{ |
|
if ( !g_pMemAlloc ) |
|
{ |
|
// core xallocs cannot be journaled until system is ready |
|
return; |
|
} |
|
|
|
AUTO_LOCK_FM( g_XMemAllocMutex ); |
|
int size = XMemSize( p, dwAllocAttributes ); |
|
MemAlloc_RegisterExternalAllocation( XMem, p, size ); |
|
} |
|
|
|
void XMemAlloc_RegisterDeallocation( void *p, DWORD dwAllocAttributes ) |
|
{ |
|
if ( !g_pMemAlloc ) |
|
{ |
|
// core xallocs cannot be journaled until system is ready |
|
return; |
|
} |
|
|
|
AUTO_LOCK_FM( g_XMemAllocMutex ); |
|
int size = XMemSize( p, dwAllocAttributes ); |
|
MemAlloc_RegisterExternalDeallocation( XMem, p, size ); |
|
} |
|
|
|
#else |
|
|
|
#define XMemAlloc_RegisterAllocation( p, a ) ((void)0) |
|
#define XMemAlloc_RegisterDeallocation( p, a ) ((void)0) |
|
|
|
#endif |
|
|
|
//----------------------------------------------------------------------------- |
|
// XMemAlloc |
|
// |
|
// XBox Memory Allocator Override |
|
//----------------------------------------------------------------------------- |
|
LPVOID WINAPI XMemAlloc( SIZE_T dwSize, DWORD dwAllocAttributes ) |
|
{ |
|
LPVOID ptr; |
|
XALLOC_ATTRIBUTES *pAttribs = (XALLOC_ATTRIBUTES *)&dwAllocAttributes; |
|
bool bPhysical = ( pAttribs->dwMemoryType == XALLOC_MEMTYPE_PHYSICAL ); |
|
|
|
if ( !bPhysical && !pAttribs->dwHeapTracksAttributes && pAttribs->dwAllocatorId != eXALLOCAllocatorId_XUI ) |
|
{ |
|
MEM_ALLOC_CREDIT(); |
|
switch ( pAttribs->dwAlignment ) |
|
{ |
|
case XALLOC_ALIGNMENT_4: |
|
ptr = g_pMemAlloc->Alloc( dwSize ); |
|
break; |
|
case XALLOC_ALIGNMENT_8: |
|
ptr = MemAlloc_AllocAligned( dwSize, 8 ); |
|
break; |
|
case XALLOC_ALIGNMENT_DEFAULT: |
|
case XALLOC_ALIGNMENT_16: |
|
default: |
|
ptr = MemAlloc_AllocAligned( dwSize, 16 ); |
|
break; |
|
} |
|
if ( pAttribs->dwZeroInitialize != 0 ) |
|
{ |
|
memset( ptr, 0, XMemSize( ptr, dwAllocAttributes ) ); |
|
} |
|
return ptr; |
|
} |
|
|
|
ptr = XMemAllocDefault( dwSize, dwAllocAttributes ); |
|
if ( ptr ) |
|
{ |
|
XMemAlloc_RegisterAllocation( ptr, dwAllocAttributes ); |
|
} |
|
|
|
return ptr; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// XMemFree |
|
// |
|
// XBox Memory Allocator Override |
|
//----------------------------------------------------------------------------- |
|
VOID WINAPI XMemFree( PVOID pAddress, DWORD dwAllocAttributes ) |
|
{ |
|
if ( !pAddress ) |
|
{ |
|
return; |
|
} |
|
|
|
XALLOC_ATTRIBUTES *pAttribs = (XALLOC_ATTRIBUTES *)&dwAllocAttributes; |
|
bool bPhysical = ( pAttribs->dwMemoryType == XALLOC_MEMTYPE_PHYSICAL ); |
|
|
|
if ( !bPhysical && !pAttribs->dwHeapTracksAttributes && pAttribs->dwAllocatorId != eXALLOCAllocatorId_XUI ) |
|
{ |
|
switch ( pAttribs->dwAlignment ) |
|
{ |
|
case XALLOC_ALIGNMENT_4: |
|
return g_pMemAlloc->Free( pAddress ); |
|
default: |
|
return MemAlloc_FreeAligned( pAddress ); |
|
} |
|
return; |
|
} |
|
|
|
XMemAlloc_RegisterDeallocation( pAddress, dwAllocAttributes ); |
|
|
|
XMemFreeDefault( pAddress, dwAllocAttributes ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// XMemSize |
|
// |
|
// XBox Memory Allocator Override |
|
//----------------------------------------------------------------------------- |
|
SIZE_T WINAPI XMemSize( PVOID pAddress, DWORD dwAllocAttributes ) |
|
{ |
|
XALLOC_ATTRIBUTES *pAttribs = (XALLOC_ATTRIBUTES *)&dwAllocAttributes; |
|
bool bPhysical = ( pAttribs->dwMemoryType == XALLOC_MEMTYPE_PHYSICAL ); |
|
|
|
if ( !bPhysical && !pAttribs->dwHeapTracksAttributes && pAttribs->dwAllocatorId != eXALLOCAllocatorId_XUI ) |
|
{ |
|
switch ( pAttribs->dwAlignment ) |
|
{ |
|
case XALLOC_ALIGNMENT_4: |
|
return g_pMemAlloc->GetSize( pAddress ); |
|
default: |
|
return MemAlloc_GetSizeAligned( pAddress ); |
|
} |
|
} |
|
|
|
return XMemSizeDefault( pAddress, dwAllocAttributes ); |
|
} |
|
#endif |
|
|
|
#pragma warning(push) |
|
#pragma warning(disable: 4483) |
|
#if _MSC_FULL_VER >= 140050415 |
|
#define _NATIVE_STARTUP_NAMESPACE __identifier("<CrtImplementationDetails>") |
|
#else /* _MSC_FULL_VER >= 140050415 */ |
|
#define _NATIVE_STARTUP_NAMESPACE __CrtImplementationDetails |
|
#endif /* _MSC_FULL_VER >= 140050415 */ |
|
|
|
namespace _NATIVE_STARTUP_NAMESPACE |
|
{ |
|
class NativeDll |
|
{ |
|
private: |
|
static const unsigned int ProcessDetach = 0; |
|
static const unsigned int ProcessAttach = 1; |
|
static const unsigned int ThreadAttach = 2; |
|
static const unsigned int ThreadDetach = 3; |
|
static const unsigned int ProcessVerifier = 4; |
|
|
|
public: |
|
|
|
inline static bool IsInDllMain() |
|
{ |
|
return false; |
|
} |
|
|
|
inline static bool IsInProcessAttach() |
|
{ |
|
return false; |
|
} |
|
|
|
inline static bool IsInProcessDetach() |
|
{ |
|
return false; |
|
} |
|
|
|
inline static bool IsInVcclrit() |
|
{ |
|
return false; |
|
} |
|
|
|
inline static bool IsSafeForManagedCode() |
|
{ |
|
if (!IsInDllMain()) |
|
{ |
|
return true; |
|
} |
|
|
|
if (IsInVcclrit()) |
|
{ |
|
return true; |
|
} |
|
|
|
return !IsInProcessAttach() && !IsInProcessDetach(); |
|
} |
|
}; |
|
} |
|
#pragma warning(pop) |
|
|
|
#endif // _MSC_VER >= 1400 |
|
|
|
#endif // !STEAM && !NO_MALLOC_OVERRIDE |
|
|
|
#endif // _WIN32
|
|
|