//========= 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 #endif #include "tier0/dbg.h" #include "tier0/memalloc.h" #include #include #include "memdbgoff.h" #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 #elif POSIX #define __cdecl #endif #undef _calloc_dbg #undef _free_dbg #undef _CrtSetCheckCount #undef _CrtGetCheckCount #undef _CrtSetDebugFillThreshold #if defined( _WIN32 ) && !defined( _X360 ) const char* MakeModuleFileName() { #if _MSC_VER < 1900 if (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(mbi.AllocationBase), pszModuleName, MAX_PATH); char* pDot = strrchr(pszModuleName, '.'); if (pDot) { char* pSlash = strrchr(pszModuleName, '\\'); if (pSlash) { pszModuleName = pSlash + 1; *pDot = 0; } } return pszModuleName; } #endif return NULL; } static void* AllocUnattributed(size_t nSize) { #if _MSC_VER < 1900 static const char* pszOwner = MakeModuleFileName(); if (!pszOwner) return g_pMemAlloc->Alloc(nSize); else return g_pMemAlloc->Alloc(nSize, pszOwner, 0); #else return g_pMemAlloc->Alloc(nSize); #endif } static void* ReallocUnattributed(void* pMem, size_t nSize) { #if _MSC_VER < 1900 static const char* pszOwner = MakeModuleFileName(); if (!pszOwner) return g_pMemAlloc->Realloc(pMem, nSize); else return g_pMemAlloc->Realloc(pMem, nSize, pszOwner, 0); #else return g_pMemAlloc->Realloc(pMem, nSize); #endif } #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 && !defined(_CRTNOALIAS) #define _CRTNOALIAS #endif #if _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); } #elif _MSC_VER >= 1900 __declspec(restrict) void* _malloc_base(size_t nSize) { return AllocUnattributed(nSize); } #else void* _malloc_base(size_t nSize) { return AllocUnattributed(nSize); } #endif #if _MSC_VER >= 1900 __declspec(restrict) void* _calloc_base(size_t count, size_t size) { void* pMem = AllocUnattributed(count * size); memset(pMem, 0, count * size); return pMem; } #else void* _calloc_base(size_t nSize) { void* pMem = AllocUnattributed(nSize); memset(pMem, 0, nSize); return pMem; } #endif #if _MSC_VER >= 1900 __declspec(restrict) void* _realloc_base(void* pMem, size_t nSize) { return ReallocUnattributed(pMem, nSize); } #else void* _realloc_base(void* pMem, size_t nSize) { return ReallocUnattributed(pMem, nSize); } #endif #if _MSC_VER >= 1900 __declspec(restrict) void* _recalloc_base(void* pMem, size_t count, size_t nSize) { return _recalloc(pMem, count, nSize); } #else void* _recalloc_base(void* pMem, size_t nSize) { return _recalloc(pMem, 1, nSize); } #endif 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) { #if _MSC_VER >= 1900 return _calloc_base(count, size); #else return _calloc_base(count * size); #endif } 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) { #if _MSC_VER >= 1900 return _recalloc_base(ptr, count, size); #else return _recalloc_base(ptr, size * count); #endif } ALLOC_CALL void* __cdecl _recalloc(void* memblock, size_t count, size_t size) { const size_t oldSize = _msize(memblock); const size_t newSize = count * size; void* pMemOut = ReallocUnattributed(memblock, newSize); if (newSize > oldSize) memset(((char*)pMemOut) + oldSize, 0, newSize - oldSize); return pMemOut; } 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 #ifdef OSX 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); } #ifdef OSX void __cdecl operator delete(void* pMem) throw() #else void __cdecl operator delete(void* pMem) #endif { g_pMemAlloc->Free(pMem); } #ifdef OSX 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); } #ifdef OSX 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); } #ifdef DEBUG void* __cdecl _malloc_dbg(size_t nSize, int nBlockUse, const char* pFileName, int nLine) { AttribIfCrt(); return g_pMemAlloc->Alloc(nSize, pFileName, nLine); } #endif // DEBUG #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 #if 1 //def DEBUG 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; } #endif // DEBUG 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); } #ifdef DEBUG 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; } #endif void __cdecl _free_dbg(void* pMem, int nBlockUse) { AttribIfCrt(); g_pMemAlloc->Free(pMem); } #ifdef DEBUG size_t __cdecl _msize_dbg(void* pMem, int nBlockUse) { #ifdef _WIN32 return _msize(pMem); #elif POSIX Assert("_msize_dbg unsupported"); return 0; #endif } #endif // DEBUG #ifdef _WIN32 #if defined(_DEBUG) && _MSC_VER >= 1300 // X360TBD: aligned and offset allocations may be important on the 360 // aligned base ALLOC_CALL void* __cdecl _aligned_malloc_base(size_t size, size_t align) { return MemAlloc_AllocAligned(size, align); } ALLOC_CALL void* __cdecl _aligned_realloc_base(void* ptr, size_t size, size_t align) { return MemAlloc_ReallocAligned(ptr, size, align); } 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" { #ifdef DEBUG int _CrtDumpMemoryLeaks(void) { return 0; } _CRT_DUMP_CLIENT _CrtSetDumpClient(_CRT_DUMP_CLIENT dumpClient) { return NULL; } int _CrtSetDbgFlag(int nNewFlag) { return g_pMemAlloc->CrtSetDbgFlag(nNewFlag); } #endif // DEBUG // 64-bit port. #define AFNAME(var) __p_ ## var #define AFRET(var) &var #if _MSC_VER >= 1900 int* __cdecl __p__crtDbgFlag(void) { static int dummy = _CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF; return &dummy; } long* __cdecl __p__crtBreakAlloc(void) { static long dummy = 0; return &dummy; } #else 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); } #endif void __cdecl _CrtSetDbgBlockType(void* pMem, int nBlockUse) { DebuggerBreak(); } #ifdef DEBUG _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(); } #endif // DEBUG //----------------------------------------------------------------------------- // Methods in dbgrpt.cpp //----------------------------------------------------------------------------- long _crtAssertBusy = -1; #ifdef DEBUG 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); } #endif // DEBUG 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 #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 0 // 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) { wchar_t buffer[256]; vswprintf(buffer, 256, szFormat, arglist); DevWarning("%ls", buffer); return 0; } int __cdecl _CrtDbgReportW(int nRptType, const wchar_t* szFile, int nLine, const wchar_t* szModule, const wchar_t* szFormat, ...) { wchar_t buffer[256]; va_list args; va_start(args, szFormat); vswprintf(buffer, 256, szFormat, args); va_end(args); DevWarning("%ls", buffer); 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) #else int __cdecl _VCrtDbgReportA(int nRptType, const wchar_t* szFile, int nLine, const wchar_t* szModule, const wchar_t* szFormat, va_list arglist) #endif { #if _MSC_VER >= 1900 char buffer[256]; vsnprintf(buffer, 256, szFormat, arglist); DevWarning("%s", buffer); #else wchar_t buffer[256]; vswprintf(buffer, 256, szFormat, arglist); DevWarning("%ls", buffer); #endif // _MSC_VER >= 1900 return 0; } 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; } #ifdef DEBUG // 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); return ReallocUnattributed(memblock, size * count); } 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 // DEBUG #endif #ifdef DEBUG int __cdecl _CrtReportBlockType(const void* pUserData) { return 0; } #endif // DEBUG } // 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); } #ifdef DEBUG _CRT_ALLOC_HOOK __cdecl _CrtGetAllocHook(void) { Assert(0); return NULL; } #endif // DEBUG static int __cdecl CheckBytes(unsigned char* pb, unsigned char bCheck, size_t nSize) { int bOkay = TRUE; return bOkay; } #ifdef DEBUG _CRT_DUMP_CLIENT __cdecl _CrtGetDumpClient(void) { Assert(0); return NULL; } #endif // DEBUG #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 #if defined(DEBUG) && _MSC_VER >= 1900 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); } #endif // DEBUG #if _MSC_VER < 1900 size_t __cdecl _CrtSetDebugFillThreshold(size_t _NewDebugFillThreshold) { Assert(0); return 0; } #endif //=========================================== // NEW!!! 64-bit #ifndef _DEBUG #ifndef PROTECTED_THINGS_DISABLE #if _MSC_VER < 1900 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 // _MSC_VER < 1900 #endif #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 // _X360 #define MAX_LANG_LEN 64 /* max language name length */ #define MAX_CTRY_LEN 64 /* max country name length */ #define MAX_MODIFIER_LEN 0 /* max modifier name length - n/a */ #define MAX_LC_LEN (MAX_LANG_LEN+MAX_CTRY_LEN+MAX_MODIFIER_LEN+3) #if _MSC_VER >= 1700 // VS 11 // Copied from C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\crt\src\mtdll.h #ifndef _SETLOC_STRUCT_DEFINED struct _is_ctype_compatible { unsigned long id; int is_clike; }; typedef struct setloc_struct { /* getqloc static variables */ wchar_t* pchLanguage; wchar_t* pchCountry; int iLocState; int iPrimaryLen; BOOL bAbbrevLanguage; BOOL bAbbrevCountry; UINT _cachecp; wchar_t _cachein[MAX_LC_LEN]; wchar_t _cacheout[MAX_LC_LEN]; /* _setlocale_set_cat (LC_CTYPE) static variable */ struct _is_ctype_compatible _Loc_c[5]; wchar_t _cacheLocaleName[LOCALE_NAME_MAX_LENGTH]; } _setloc_struct, * _psetloc_struct; #define _SETLOC_STRUCT_DEFINED #endif /* _SETLOC_STRUCT_DEFINED */ _CRTIMP extern unsigned long __cdecl __threadid(void); #define _threadid (__threadid()) _CRTIMP extern uintptr_t __cdecl __threadhandle(void); #define _threadhandle (__threadhandle()) /* Structure for each thread's data */ #if _MSC_VER >= 1900 typedef __crt_multibyte_data* pthreadmbcinfo; typedef __crt_locale_data* pthreadlocinfo; typedef __crt_locale_pointers _locale_tstruct; #endif struct _tiddata { unsigned long _tid; /* thread ID */ uintptr_t _thandle; /* thread handle */ int _terrno; /* errno value */ unsigned long _tdoserrno; /* _doserrno value */ unsigned int _fpds; /* Floating Point data segment */ unsigned long _holdrand; /* rand() seed value */ char* _token; /* ptr to strtok() token */ wchar_t* _wtoken; /* ptr to wcstok() token */ unsigned char* _mtoken; /* ptr to _mbstok() token */ /* following pointers get malloc'd at runtime */ char* _errmsg; /* ptr to strerror()/_strerror() buff */ wchar_t* _werrmsg; /* ptr to _wcserror()/__wcserror() buff */ char* _namebuf0; /* ptr to tmpnam() buffer */ wchar_t* _wnamebuf0; /* ptr to _wtmpnam() buffer */ char* _namebuf1; /* ptr to tmpfile() buffer */ wchar_t* _wnamebuf1; /* ptr to _wtmpfile() buffer */ char* _asctimebuf; /* ptr to asctime() buffer */ wchar_t* _wasctimebuf; /* ptr to _wasctime() buffer */ void* _gmtimebuf; /* ptr to gmtime() structure */ char* _cvtbuf; /* ptr to ecvt()/fcvt buffer */ unsigned char _con_ch_buf[MB_LEN_MAX]; /* ptr to putch() buffer */ unsigned short _ch_buf_used; /* if the _con_ch_buf is used */ /* following fields are needed by _beginthread code */ void* _initaddr; /* initial user thread address */ void* _initarg; /* initial user thread argument */ /* following three fields are needed to support signal handling and * runtime errors */ void* _pxcptacttab; /* ptr to exception-action table */ void* _tpxcptinfoptrs; /* ptr to exception info pointers */ int _tfpecode; /* float point exception code */ /* pointer to the copy of the multibyte character information used by * the thread */ pthreadmbcinfo ptmbcinfo; /* pointer to the copy of the locale informaton used by the thead */ pthreadlocinfo ptlocinfo; int _ownlocale; /* if 1, this thread owns its own locale */ /* following field is needed by NLG routines */ unsigned long _NLG_dwCode; /* * Per-Thread data needed by C++ Exception Handling */ void* _terminate; /* terminate() routine */ void* _unexpected; /* unexpected() routine */ void* _translator; /* S.E. translator */ void* _purecall; /* called when pure virtual happens */ void* _curexception; /* current exception */ void* _curcontext; /* current exception context */ int _ProcessingThrow; /* for uncaught_exception */ void* _curexcspec; /* for handling exceptions thrown from std::unexpected */ #if defined (_M_X64) || defined (_M_ARM) void* _pExitContext; void* _pUnwindContext; void* _pFrameInfoChain; #if defined (_WIN64) unsigned __int64 _ImageBase; unsigned __int64 _ThrowImageBase; #else /* defined (_WIN64) */ unsigned __int32 _ImageBase; unsigned __int32 _ThrowImageBase; #endif /* defined (_WIN64) */ void* _pForeignException; #elif defined (_M_IX86) void* _pFrameInfoChain; #endif /* defined (_M_IX86) */ _setloc_struct _setloc_data; void* _reserved1; /* nothing */ void* _reserved2; /* nothing */ void* _reserved3; /* nothing */ #ifdef _M_IX86 void* _reserved4; /* nothing */ void* _reserved5; /* nothing */ #endif /* _M_IX86 */ int _cxxReThrow; /* Set to True if it's a rethrown C++ Exception */ unsigned long __initDomain; /* initial domain used by _beginthread[ex] for managed function */ }; #else struct _is_ctype_compatible { unsigned long id; int is_clike; }; typedef struct setloc_struct { /* getqloc static variables */ char* pchLanguage; char* pchCountry; int iLcidState; int iPrimaryLen; BOOL bAbbrevLanguage; BOOL bAbbrevCountry; LCID lcidLanguage; LCID lcidCountry; /* expand_locale static variables */ LC_ID _cacheid; UINT _cachecp; char _cachein[MAX_LC_LEN]; char _cacheout[MAX_LC_LEN]; /* _setlocale_set_cat (LC_CTYPE) static variable */ struct _is_ctype_compatible _Lcid_c[5]; } _setloc_struct, * _psetloc_struct; struct _tiddata { unsigned long _tid; /* thread ID */ uintptr_t _thandle; /* thread handle */ int _terrno; /* errno value */ unsigned long _tdoserrno; /* _doserrno value */ unsigned int _fpds; /* Floating Point data segment */ unsigned long _holdrand; /* rand() seed value */ char* _token; /* ptr to strtok() token */ wchar_t* _wtoken; /* ptr to wcstok() token */ unsigned char* _mtoken; /* ptr to _mbstok() token */ /* following pointers get malloc'd at runtime */ char* _errmsg; /* ptr to strerror()/_strerror() buff */ wchar_t* _werrmsg; /* ptr to _wcserror()/__wcserror() buff */ char* _namebuf0; /* ptr to tmpnam() buffer */ wchar_t* _wnamebuf0; /* ptr to _wtmpnam() buffer */ char* _namebuf1; /* ptr to tmpfile() buffer */ wchar_t* _wnamebuf1; /* ptr to _wtmpfile() buffer */ char* _asctimebuf; /* ptr to asctime() buffer */ wchar_t* _wasctimebuf; /* ptr to _wasctime() buffer */ void* _gmtimebuf; /* ptr to gmtime() structure */ char* _cvtbuf; /* ptr to ecvt()/fcvt buffer */ unsigned char _con_ch_buf[MB_LEN_MAX]; /* ptr to putch() buffer */ unsigned short _ch_buf_used; /* if the _con_ch_buf is used */ /* following fields are needed by _beginthread code */ void* _initaddr; /* initial user thread address */ void* _initarg; /* initial user thread argument */ /* following three fields are needed to support signal handling and * runtime errors */ void* _pxcptacttab; /* ptr to exception-action table */ void* _tpxcptinfoptrs; /* ptr to exception info pointers */ int _tfpecode; /* float point exception code */ /* pointer to the copy of the multibyte character information used by * the thread */ pthreadmbcinfo ptmbcinfo; /* pointer to the copy of the locale informaton used by the thead */ pthreadlocinfo ptlocinfo; int _ownlocale; /* if 1, this thread owns its own locale */ /* following field is needed by NLG routines */ unsigned long _NLG_dwCode; /* * Per-Thread data needed by C++ Exception Handling */ void* _terminate; /* terminate() routine */ void* _unexpected; /* unexpected() routine */ void* _translator; /* S.E. translator */ void* _purecall; /* called when pure virtual happens */ void* _curexception; /* current exception */ void* _curcontext; /* current exception context */ int _ProcessingThrow; /* for uncaught_exception */ void* _curexcspec; /* for handling exceptions thrown from std::unexpected */ #if defined (_M_IA64) || defined (_M_AMD64) void* _pExitContext; void* _pUnwindContext; void* _pFrameInfoChain; unsigned __int64 _ImageBase; #if defined (_M_IA64) unsigned __int64 _TargetGp; #endif /* defined (_M_IA64) */ unsigned __int64 _ThrowImageBase; void* _pForeignException; #elif defined (_M_IX86) void* _pFrameInfoChain; #endif /* defined (_M_IX86) */ _setloc_struct _setloc_data; void* _encode_ptr; /* EncodePointer() routine */ void* _decode_ptr; /* DecodePointer() routine */ void* _reserved1; /* nothing */ void* _reserved2; /* nothing */ void* _reserved3; /* nothing */ int _cxxReThrow; /* Set to True if it's a rethrown C++ Exception */ unsigned long __initDomain; /* initial domain used by _beginthread[ex] for managed function */ }; #endif typedef struct _tiddata* _ptiddata; class _LocaleUpdate { _locale_tstruct localeinfo; _ptiddata ptd; bool updated; public: _LocaleUpdate(_locale_t plocinfo) : updated(false) { /* if (plocinfo == NULL) { ptd = _getptd(); localeinfo.locinfo = ptd->ptlocinfo; localeinfo.mbcinfo = ptd->ptmbcinfo; __UPDATE_LOCALE(ptd, localeinfo.locinfo); __UPDATE_MBCP(ptd, localeinfo.mbcinfo); if (!(ptd->_ownlocale & _PER_THREAD_LOCALE_BIT)) { ptd->_ownlocale |= _PER_THREAD_LOCALE_BIT; updated = true; } } else { localeinfo=*plocinfo; } */ } ~_LocaleUpdate() { // if (updated) // ptd->_ownlocale = ptd->_ownlocale & ~_PER_THREAD_LOCALE_BIT; } _locale_t GetLocaleT() { return &localeinfo; } }; #pragma warning(push) #pragma warning(disable: 4483) #if _MSC_FULL_VER >= 140050415 #define _NATIVE_STARTUP_NAMESPACE __identifier("") #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