home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / afxmem.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  10KB  |  397 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_CORE1_SEG
  14. #pragma code_seg(AFX_CORE1_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. /////////////////////////////////////////////////////////////////////////////
  23. // Debug memory globals and implementation helpers
  24.  
  25. #ifdef _DEBUG       // most of this file is for debugging
  26.  
  27. void* __cdecl operator new(size_t nSize, int nType, LPCSTR lpszFileName, int nLine);
  28.  
  29. /////////////////////////////////////////////////////////////////////////////
  30. // test allocation routines
  31.  
  32. void* PASCAL CObject::operator new(size_t nSize)
  33. {
  34. #ifdef _AFX_NO_DEBUG_CRT
  35.     return ::operator new(nSize);
  36. #else
  37.     return ::operator new(nSize, _CLIENT_BLOCK, NULL, 0);
  38. #endif // _AFX_NO_DEBUG_CRT
  39. }
  40.  
  41. void PASCAL CObject::operator delete(void* p)
  42. {
  43. #ifdef _AFX_NO_DEBUG_CRT
  44.     free(p);
  45. #else
  46.     _free_dbg(p, _CLIENT_BLOCK);
  47. #endif
  48. }
  49.  
  50. #if _MSC_VER >= 1200
  51. void PASCAL CObject::operator delete(void* p, void*)
  52. {
  53. #ifdef _AFX_NO_DEBUG_CRT
  54.     free(p);
  55. #else
  56.     _free_dbg(p, _CLIENT_BLOCK);
  57. #endif
  58. }
  59. #endif
  60.  
  61. #ifndef _AFX_NO_DEBUG_CRT
  62.  
  63. void* AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
  64. {
  65.     return ::operator new(nSize, _NORMAL_BLOCK, lpszFileName, nLine);
  66. }
  67.  
  68. #if _MSC_VER >= 1200
  69. void AFX_CDECL operator delete(void* pData, LPCSTR /* lpszFileName */,
  70.     int /* nLine */)
  71. {
  72.     ::operator delete(pData);
  73. }
  74. #endif
  75.  
  76. void* PASCAL
  77. CObject::operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
  78. {
  79.     return ::operator new(nSize, _CLIENT_BLOCK, lpszFileName, nLine);
  80. }
  81.  
  82. #if _MSC_VER >= 1200
  83. void PASCAL
  84. CObject::operator delete(void *pObject, LPCSTR /* lpszFileName */,
  85.     int /* nLine */)
  86. {
  87. #ifdef _AFX_NO_DEBUG_CRT
  88.     free(pObject);
  89. #else
  90.     _free_dbg(pObject, _CLIENT_BLOCK);
  91. #endif
  92. }
  93. #endif
  94.  
  95. void* AFXAPI AfxAllocMemoryDebug(size_t nSize, BOOL bIsObject,  LPCSTR lpszFileName, int nLine)
  96. {
  97.     return _malloc_dbg(nSize, bIsObject ? _CLIENT_BLOCK : _NORMAL_BLOCK,
  98.         lpszFileName, nLine);
  99. }
  100.  
  101. void AFXAPI AfxFreeMemoryDebug(void* pbData, BOOL bIsObject)
  102. {
  103.     _free_dbg(pbData, bIsObject ? _CLIENT_BLOCK : _NORMAL_BLOCK);
  104. }
  105.  
  106. /////////////////////////////////////////////////////////////////////////////
  107. // allocation failure hook, tracking turn on
  108.  
  109. BOOL AFXAPI _AfxDefaultAllocHook(size_t, BOOL, LONG)
  110.     { return TRUE; }
  111.  
  112. AFX_STATIC_DATA AFX_ALLOC_HOOK pfnAllocHook = _AfxDefaultAllocHook;
  113.  
  114. AFX_STATIC_DATA _CRT_ALLOC_HOOK pfnCrtAllocHook = NULL;
  115. #if _MSC_VER >= 1200
  116. int __cdecl _AfxAllocHookProxy(int nAllocType, void * pvData, size_t nSize,
  117.     int nBlockUse, long lRequest, const unsigned char * szFilename, int nLine)
  118. #else
  119. int __cdecl _AfxAllocHookProxy(int nAllocType, void * pvData, size_t nSize,
  120.     int nBlockUse, long lRequest, const char * szFilename, int nLine)
  121. #endif
  122. {
  123. #if _MSC_VER >= 1200
  124.     if (nAllocType != _HOOK_ALLOC)
  125.         return (pfnCrtAllocHook)(nAllocType, pvData, nSize,
  126.             nBlockUse, lRequest, (const unsigned char*) szFilename, nLine);
  127.     if ((pfnAllocHook)(nSize, _BLOCK_TYPE(nBlockUse) == _CLIENT_BLOCK, lRequest))
  128.         return (pfnCrtAllocHook)(nAllocType, pvData, nSize,
  129.             nBlockUse, lRequest, (const unsigned char*) szFilename, nLine);
  130. #else
  131.     if (nAllocType != _HOOK_ALLOC)
  132.         return (pfnCrtAllocHook)(nAllocType, pvData, nSize,
  133.             nBlockUse, lRequest, szFilename, nLine);
  134.     if ((pfnAllocHook)(nSize, _BLOCK_TYPE(nBlockUse) == _CLIENT_BLOCK, lRequest))
  135.         return (pfnCrtAllocHook)(nAllocType, pvData, nSize,
  136.             nBlockUse, lRequest, szFilename, nLine);
  137. #endif
  138.     return FALSE;
  139. }
  140.  
  141. AFX_ALLOC_HOOK AFXAPI AfxSetAllocHook(AFX_ALLOC_HOOK pfnNewHook)
  142. {
  143.     if (pfnCrtAllocHook == NULL)
  144.         pfnCrtAllocHook = _CrtSetAllocHook(_AfxAllocHookProxy);
  145.  
  146.     AFX_ALLOC_HOOK pfnOldHook = pfnAllocHook;
  147.     pfnAllocHook = pfnNewHook;
  148.     return pfnOldHook;
  149. }
  150.  
  151. // This can be set to TRUE to override all AfxEnableMemoryTracking calls,
  152. // allowing all allocations, even MFC internal allocations to be tracked.
  153. BOOL _afxMemoryLeakOverride = FALSE;
  154.  
  155. BOOL AFXAPI AfxEnableMemoryTracking(BOOL bTrack)
  156. {
  157.     if (_afxMemoryLeakOverride)
  158.         return TRUE;
  159.  
  160.     int nOldState = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
  161.     if (bTrack)
  162.         _CrtSetDbgFlag(nOldState | _CRTDBG_ALLOC_MEM_DF);
  163.     else
  164.         _CrtSetDbgFlag(nOldState & ~_CRTDBG_ALLOC_MEM_DF);
  165.     return nOldState & _CRTDBG_ALLOC_MEM_DF;
  166. }
  167.  
  168. /////////////////////////////////////////////////////////////////////////////
  169. // stop on a specific memory request
  170.  
  171. // Obsolete API
  172. void AFXAPI AfxSetAllocStop(LONG lRequestNumber)
  173. {
  174.     _CrtSetBreakAlloc(lRequestNumber);
  175. }
  176.  
  177. BOOL AFXAPI AfxCheckMemory()
  178.   // check all of memory (look for memory tromps)
  179. {
  180.     return _CrtCheckMemory();
  181. }
  182.  
  183. // -- true if block of exact size, allocated on the heap
  184. // -- set *plRequestNumber to request number (or 0)
  185. BOOL AFXAPI AfxIsMemoryBlock(const void* pData, UINT nBytes,
  186.         LONG* plRequestNumber)
  187. {
  188.     return _CrtIsMemoryBlock(pData, nBytes, plRequestNumber, NULL, NULL);
  189. }
  190.  
  191. /////////////////////////////////////////////////////////////////////////////
  192. // CMemoryState
  193.  
  194. CMemoryState::CMemoryState()
  195. {
  196.     memset(this, 0, sizeof(*this));
  197. }
  198.  
  199. void CMemoryState::UpdateData()
  200. {
  201.     for(int i = 0; i < nBlockUseMax; i++)
  202.     {
  203.         m_lCounts[i] = m_memState.lCounts[i];
  204.         m_lSizes[i] = m_memState.lSizes[i];
  205.     }
  206.     m_lHighWaterCount = m_memState.lHighWaterCount;
  207.     m_lTotalCount = m_memState.lTotalCount;
  208. }
  209.  
  210. // fills 'this' with the difference, returns TRUE if significant
  211. BOOL CMemoryState::Difference(const CMemoryState& oldState,
  212.         const CMemoryState& newState)
  213. {
  214.     int nResult = _CrtMemDifference(&m_memState, &oldState.m_memState, &newState.m_memState);
  215.     UpdateData();
  216.     return nResult != 0;
  217. }
  218.  
  219. void CMemoryState::DumpStatistics() const
  220. {
  221.     _CrtMemDumpStatistics(&m_memState);
  222. }
  223.  
  224. // -- fill with current memory state
  225. void CMemoryState::Checkpoint()
  226. {
  227.     _CrtMemCheckpoint(&m_memState);
  228.     UpdateData();
  229. }
  230.  
  231. // Dump objects created after this memory state was checkpointed
  232. // Will dump all objects if this memory state wasn't checkpointed
  233. // Dump all objects, report about non-objects also
  234. // List request number in {}
  235. void CMemoryState::DumpAllObjectsSince() const
  236. {
  237.     _CrtMemDumpAllObjectsSince(&m_memState);
  238. }
  239.  
  240. /////////////////////////////////////////////////////////////////////////////
  241. // Enumerate all objects allocated in the diagnostic memory heap
  242.  
  243. struct _AFX_ENUM_CONTEXT
  244. {
  245.     void (*m_pfn)(CObject*,void*);
  246.     void* m_pContext;
  247. };
  248.  
  249. AFX_STATIC void _AfxDoForAllObjectsProxy(void* pObject, void* pContext)
  250. {
  251.     _AFX_ENUM_CONTEXT* p = (_AFX_ENUM_CONTEXT*)pContext;
  252.     (*p->m_pfn)((CObject*)pObject, p->m_pContext);
  253. }
  254.  
  255. void AFXAPI
  256. AfxDoForAllObjects(void (AFX_CDECL *pfn)(CObject*, void*), void* pContext)
  257. {
  258.     _AFX_ENUM_CONTEXT context;
  259.     context.m_pfn = pfn;
  260.     context.m_pContext = pContext;
  261.     _CrtDoForAllClientObjects(_AfxDoForAllObjectsProxy, &context);
  262. }
  263.  
  264. /////////////////////////////////////////////////////////////////////////////
  265. // Automatic debug memory diagnostics
  266.  
  267. BOOL AFXAPI AfxDumpMemoryLeaks()
  268. {
  269.     return _CrtDumpMemoryLeaks();
  270. }
  271.  
  272. #endif // _AFX_NO_DEBUG_CRT
  273. #endif // _DEBUG
  274.  
  275. /////////////////////////////////////////////////////////////////////////////
  276. // Non-diagnostic memory routines
  277.  
  278. int AFX_CDECL AfxNewHandler(size_t /* nSize */)
  279. {
  280.     AfxThrowMemoryException();
  281.     return 0;
  282. }
  283.  
  284. #pragma warning(disable: 4273)
  285.  
  286. #ifndef _AFXDLL
  287. AFX_COMDAT _PNH _afxNewHandler = &AfxNewHandler;
  288. #endif
  289.  
  290. _PNH AFXAPI AfxGetNewHandler(void)
  291. {
  292. #ifdef _AFXDLL
  293.     AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
  294.     return pState->m_pfnNewHandler;
  295. #else
  296.     return _afxNewHandler;
  297. #endif
  298. }
  299.  
  300. _PNH AFXAPI AfxSetNewHandler(_PNH pfnNewHandler)
  301. {
  302. #ifdef _AFXDLL
  303.     AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
  304.     _PNH pfnOldHandler = pState->m_pfnNewHandler;
  305.     pState->m_pfnNewHandler = pfnNewHandler;
  306.     return pfnOldHandler;
  307. #else
  308.     _PNH pfnOldHandler = _afxNewHandler;
  309.     _afxNewHandler = pfnNewHandler;
  310.     return pfnOldHandler;
  311. #endif
  312. }
  313.  
  314. AFX_STATIC_DATA const _PNH _pfnUninitialized = (_PNH)-1;
  315.  
  316. void* __cdecl operator new(size_t nSize)
  317. {
  318.     void* pResult;
  319. #ifdef _AFXDLL
  320.     _PNH pfnNewHandler = _pfnUninitialized;
  321. #endif
  322.     for (;;)
  323.     {
  324. #if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG)
  325.         pResult = _malloc_dbg(nSize, _NORMAL_BLOCK, NULL, 0);
  326. #else
  327.         pResult = malloc(nSize);
  328. #endif
  329.         if (pResult != NULL)
  330.             return pResult;
  331.  
  332. #ifdef _AFXDLL
  333.         if (pfnNewHandler == _pfnUninitialized)
  334.         {
  335.             AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
  336.             pfnNewHandler = pState->m_pfnNewHandler;
  337.         }
  338.         if (pfnNewHandler == NULL || (*pfnNewHandler)(nSize) == 0)
  339.             break;
  340. #else
  341.         if (_afxNewHandler == NULL || (*_afxNewHandler)(nSize) == 0)
  342.             break;
  343. #endif
  344.     }
  345.     return pResult;
  346. }
  347.  
  348. void __cdecl operator delete(void* p)
  349. {
  350. #if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG)
  351.         _free_dbg(p, _NORMAL_BLOCK);
  352. #else
  353.         free(p);
  354. #endif
  355. }
  356.  
  357. #ifdef _DEBUG
  358.  
  359. void* __cdecl operator new(size_t nSize, int nType, LPCSTR lpszFileName, int nLine)
  360. {
  361. #ifdef _AFX_NO_DEBUG_CRT
  362.     UNUSED_ALWAYS(nType);
  363.     UNUSED_ALWAYS(lpszFileName);
  364.     UNUSED_ALWAYS(nLine);
  365.     return ::operator new(nSize);
  366. #else
  367.     void* pResult;
  368. #ifdef _AFXDLL
  369.     _PNH pfnNewHandler = _pfnUninitialized;
  370. #endif
  371.     for (;;)
  372.     {
  373.         pResult = _malloc_dbg(nSize, nType, lpszFileName, nLine);
  374.         if (pResult != NULL)
  375.             return pResult;
  376.  
  377. #ifdef _AFXDLL
  378.         if (pfnNewHandler == _pfnUninitialized)
  379.         {
  380.             AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
  381.             pfnNewHandler = pState->m_pfnNewHandler;
  382.         }
  383.         if (pfnNewHandler == NULL || (*pfnNewHandler)(nSize) == 0)
  384.             break;
  385. #else
  386.         if (_afxNewHandler == NULL || (*_afxNewHandler)(nSize) == 0)
  387.             break;
  388. #endif
  389.     }
  390.     return pResult;
  391. #endif
  392. }
  393.  
  394. #endif //_DEBUG
  395.  
  396. /////////////////////////////////////////////////////////////////////////////
  397.