1 ////////////////////////////////////////////////////////////////////////////////
2 // $Id: vld.cpp,v 1.69 2006/11/18 05:07:04 dmouldin Exp $
4 // Visual Leak Detector - VisualLeakDetector Class Implementation
5 // Copyright (c) 2005-2006 Dan Moulding
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Lesser General Public License for more details.
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this library; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 // See COPYING.txt for the full terms of the GNU Lesser General Public License.
23 ////////////////////////////////////////////////////////////////////////////////
25 #pragma comment(lib, "dbghelp.lib")
32 #define __out_xcount(x) // Workaround for the specstrings.h bug in the Platform SDK.
33 #define DBGHELP_TRANSLATE_TCHAR
34 #include <dbghelp.h> // Provides symbol handling services.
35 #define VLDBUILD // Declares that we are building Visual Leak Detector.
36 #include "callstack.h" // Provides a class for handling call stacks.
37 #include "map.h" // Provides a lightweight STL-like map template.
38 #include "ntapi.h" // Provides access to NT APIs.
39 #include "set.h" // Provides a lightweight STL-like set template.
40 #include "utility.h" // Provides various utility functions.
41 #include "vldheap.h" // Provides internal new and delete operators.
42 #include "vldint.h" // Provides access to the Visual Leak Detector internals.
44 #define BLOCKMAPRESERVE 64 // This should strike a balance between memory use and a desire to minimize heap hits.
45 #define HEAPMAPRESERVE 2 // Usually there won't be more than a few heaps in the process, so this should be small.
46 #define MAXSYMBOLNAMELENGTH 256 // Maximum symbol name length that we will allow. Longer names will be truncated.
47 #define MODULESETRESERVE 16 // There are likely to be several modules loaded in the process.
49 // Imported global variables.
50 extern vldblockheader_t *vldblocklist;
51 extern HANDLE vldheap;
52 extern CRITICAL_SECTION vldheaplock;
55 HANDLE currentprocess; // Pseudo-handle for the current process.
56 HANDLE currentthread; // Pseudo-handle for the current thread.
57 CRITICAL_SECTION imagelock; // Serializes calls to the Debug Help Library PE image access APIs.
58 HANDLE processheap; // Handle to the process's heap (COM allocations come from here).
59 CRITICAL_SECTION stackwalklock; // Serializes calls to StackWalk64 from the Debug Help Library.
60 CRITICAL_SECTION symbollock; // Serializes calls to the Debug Help Library symbold handling APIs.
62 // Function pointer types for explicit dynamic linking with functions listed in
63 // the import patch table.
64 typedef void* (__cdecl *_calloc_dbg_t) (size_t, size_t, int, const char*, int);
65 typedef void* (__cdecl *_malloc_dbg_t) (size_t, int, const char *, int);
66 typedef void* (__cdecl *_realloc_dbg_t) (void *, size_t, int, const char *, int);
67 typedef void* (__cdecl *calloc_t) (size_t, size_t);
68 typedef HRESULT (__stdcall *CoGetMalloc_t) (DWORD, LPMALLOC *);
69 typedef LPVOID (__stdcall *CoTaskMemAlloc_t) (ULONG);
70 typedef LPVOID (__stdcall *CoTaskMemRealloc_t) (LPVOID, ULONG);
71 typedef void* (__cdecl *crt_new_dbg_t) (unsigned int, int, const char *, int);
72 typedef void* (__cdecl *malloc_t) (size_t);
73 typedef void* (__cdecl *mfc_new_dbg_t) (unsigned int, const char *, int);
74 typedef void* (__cdecl *new_t) (unsigned int);
75 typedef void* (__cdecl *realloc_t) (void *, size_t);
77 // Global function pointers for explicit dynamic linking with functions listed
78 // in the import patch table. Using explicit dynamic linking minimizes VLD's
79 // footprint by loading only modules that are actually used. These pointers will
80 // be linked to the real functions the first time they are used.
81 static CoGetMalloc_t pCoGetMalloc = NULL;
82 static CoTaskMemAlloc_t pCoTaskMemAlloc = NULL;
83 static CoTaskMemRealloc_t pCoTaskMemRealloc = NULL;
84 static _calloc_dbg_t pcrt80d__calloc_dbg = NULL;
85 static _malloc_dbg_t pcrt80d__malloc_dbg = NULL;
86 static _realloc_dbg_t pcrt80d__realloc_dbg = NULL;
87 static crt_new_dbg_t pcrt80d__scalar_new_dbg = NULL;
88 static crt_new_dbg_t pcrt80d__vector_new_dbg = NULL;
89 static calloc_t pcrt80d_calloc = NULL;
90 static malloc_t pcrt80d_malloc = NULL;
91 static realloc_t pcrt80d_realloc = NULL;
92 static new_t pcrt80d_scalar_new = NULL;
93 static new_t pcrt80d_vector_new = NULL;
94 static _calloc_dbg_t pcrtd__calloc_dbg = NULL;
95 static _malloc_dbg_t pcrtd__malloc_dbg = NULL;
96 static _realloc_dbg_t pcrtd__realloc_dbg = NULL;
97 static crt_new_dbg_t pcrtd__scalar_new_dbg = NULL;
98 static calloc_t pcrtd_calloc = NULL;
99 static malloc_t pcrtd_malloc = NULL;
100 static realloc_t pcrtd_realloc = NULL;
101 static new_t pcrtd_scalar_new = NULL;
102 static mfc_new_dbg_t pmfc42d__scalar_new_dbg = NULL;
103 static new_t pmfc42d_scalar_new = NULL;
104 static mfc_new_dbg_t pmfc80d__scalar_new_dbg = NULL;
105 static mfc_new_dbg_t pmfc80d__vector_new_dbg = NULL;
106 static new_t pmfc80d_scalar_new = NULL;
107 static new_t pmfc80d_vector_new = NULL;
109 // The one and only VisualLeakDetector object instance.
110 __declspec(dllexport) VisualLeakDetector vld;
112 // The import patch table: lists the heap-related API imports that VLD patches
113 // through to replacement functions provided by VLD. Having this table simply
114 // makes it more convenient to add additional IAT patches.
115 patchentry_t VisualLeakDetector::m_patchtable [] = {
117 "kernel32.dll", "GetProcAddress", 0x0, _GetProcAddress, // Not heap related, but can be used to obtain pointers to heap functions.
118 "kernel32.dll", "HeapAlloc", 0x0, _RtlAllocateHeap,
119 "kernel32.dll", "HeapCreate", 0x0, _HeapCreate,
120 "kernel32.dll", "HeapDestroy", 0x0, _HeapDestroy,
121 "kernel32.dll", "HeapFree", 0x0, _RtlFreeHeap,
122 "kernel32.dll", "HeapReAlloc", 0x0, _RtlReAllocateHeap,
124 // MFC new operators (exported by ordinal).
125 "mfc42d.dll", (LPCSTR)714, 0x0, _mfc42d__scalar_new_dbg,
126 "mfc42d.dll", (LPCSTR)711, 0x0, _mfc42d_scalar_new,
127 // XXX MFC 7.x DLL new operators still need to be added to this
128 // table, but I don't know their ordinals.
129 "mfc80d.dll", (LPCSTR)895, 0x0, _mfc80d__scalar_new_dbg,
130 "mfc80d.dll", (LPCSTR)269, 0x0, _mfc80d__vector_new_dbg,
131 "mfc80d.dll", (LPCSTR)893, 0x0, _mfc80d_scalar_new,
132 "mfc80d.dll", (LPCSTR)267, 0x0, _mfc80d_vector_new,
134 // CRT new operators and heap APIs.
135 "msvcr80d.dll", "_calloc_dbg", 0x0, _crt80d__calloc_dbg,
136 "msvcr80d.dll", "_malloc_dbg", 0x0, _crt80d__malloc_dbg,
137 "msvcr80d.dll", "_realloc_dbg", 0x0, _crt80d__realloc_dbg,
138 "msvcr80d.dll", "??2@YAPAXIHPBDH@Z", 0x0, _crt80d__scalar_new_dbg,
139 "msvcr80d.dll", "??_U@YAPAXIHPBDH@Z", 0x0, _crt80d__vector_new_dbg,
140 "msvcr80d.dll", "calloc", 0x0, _crt80d_calloc,
141 "msvcr80d.dll", "malloc", 0x0, _crt80d_malloc,
142 "msvcr80d.dll", "realloc", 0x0, _crt80d_realloc,
143 "msvcr80d.dll", "??2@YAPAXI@Z", 0x0, _crt80d_scalar_new,
144 "msvcr80d.dll", "??_U@YAPAXI@Z", 0x0, _crt80d_vector_new,
145 "msvcrtd.dll", "_calloc_dbg", 0x0, _crtd__calloc_dbg,
146 "msvcrtd.dll", "_malloc_dbg", 0x0, _crtd__malloc_dbg,
147 "msvcrtd.dll", "??2@YAPAXIHPBDH@Z", 0x0, _crtd__scalar_new_dbg,
148 "msvcrtd.dll", "_realloc_dbg", 0x0, _crtd__realloc_dbg,
149 "msvcrtd.dll", "calloc", 0x0, _crtd_calloc,
150 "msvcrtd.dll", "malloc", 0x0, _crtd_malloc,
151 "msvcrtd.dll", "realloc", 0x0, _crtd_realloc,
152 "msvcrtd.dll", "??2@YAPAXI@Z", 0x0, _crtd_scalar_new,
155 "ntdll.dll", "RtlAllocateHeap", 0x0, _RtlAllocateHeap,
156 "ntdll.dll", "RtlFreeHeap", 0x0, _RtlFreeHeap,
157 "ntdll.dll", "RtlReAllocateHeap", 0x0, _RtlReAllocateHeap,
160 "ole32.dll", "CoGetMalloc", 0x0, _CoGetMalloc,
161 "ole32.dll", "CoTaskMemAlloc", 0x0, _CoTaskMemAlloc,
162 "ole32.dll", "CoTaskMemRealloc", 0x0, _CoTaskMemRealloc
165 // Constructor - Initializes private data, loads configuration options, and
166 // attaches Visual Leak Detector to all other modules loaded into the current
169 VisualLeakDetector::VisualLeakDetector ()
171 WCHAR bom = BOM; // Unicode byte-order mark.
173 ModuleSet *newmodules;
177 // Initialize configuration options and related private data.
178 _wcsnset_s(m_forcedmodulelist, MAXMODULELISTLENGTH, '\0', _TRUNCATE);
179 m_maxdatadump = 0xffffffff;
180 m_maxtraceframes = 0xffffffff;
183 wcsncpy_s(m_reportfilepath, MAX_PATH, VLD_DEFAULT_REPORT_FILE_NAME, _TRUNCATE);
186 // Load configuration options.
188 if (m_options & VLD_OPT_VLDOFF) {
189 report(L"Visual Leak Detector is turned off.\n");
193 kernel32 = GetModuleHandle(L"kernel32.dll");
194 ntdll = GetModuleHandle(L"ntdll.dll");
196 // Initialize global variables.
197 currentprocess = GetCurrentProcess();
198 currentthread = GetCurrentThread();
199 InitializeCriticalSection(&imagelock);
200 LdrLoadDll = (LdrLoadDll_t)GetProcAddress(ntdll, "LdrLoadDll");
201 processheap = GetProcessHeap();
202 RtlAllocateHeap = (RtlAllocateHeap_t)GetProcAddress(ntdll, "RtlAllocateHeap");
203 RtlFreeHeap = (RtlFreeHeap_t)GetProcAddress(ntdll, "RtlFreeHeap");
204 RtlReAllocateHeap = (RtlReAllocateHeap_t)GetProcAddress(ntdll, "RtlReAllocateHeap");
205 InitializeCriticalSection(&stackwalklock);
206 InitializeCriticalSection(&symbollock);
207 vldheap = HeapCreate(0x0, 0, 0);
208 InitializeCriticalSection(&vldheaplock);
210 // Initialize remaining private data.
211 m_heapmap = new HeapMap;
212 m_heapmap->reserve(HEAPMAPRESERVE);
215 m_loadedmodules = NULL;
216 InitializeCriticalSection(&m_loaderlock);
217 InitializeCriticalSection(&m_maplock);
218 InitializeCriticalSection(&m_moduleslock);
219 m_selftestfile = __FILE__;
221 m_tlsindex = TlsAlloc();
222 InitializeCriticalSection(&m_tlslock);
223 m_tlsset = new TlsSet;
225 if (m_options & VLD_OPT_SELF_TEST) {
226 // Self-test mode has been enabled. Intentionally leak a small amount of
227 // memory so that memory leak self-checking can be verified.
228 if (m_options & VLD_OPT_UNICODE_REPORT) {
229 wcsncpy_s(new WCHAR [wcslen(SELFTESTTEXTW) + 1], wcslen(SELFTESTTEXTW) + 1, SELFTESTTEXTW, _TRUNCATE);
230 m_selftestline = __LINE__ - 1;
233 strncpy_s(new CHAR [strlen(SELFTESTTEXTA) + 1], strlen(SELFTESTTEXTA) + 1, SELFTESTTEXTA, _TRUNCATE);
234 m_selftestline = __LINE__ - 1;
237 if (m_options & VLD_OPT_START_DISABLED) {
238 // Memory leak detection will initially be disabled.
239 m_status |= VLD_STATUS_NEVER_ENABLED;
241 if (m_options & VLD_OPT_REPORT_TO_FILE) {
242 // Reporting to file enabled.
243 if (m_options & VLD_OPT_UNICODE_REPORT) {
244 // Unicode data encoding has been enabled. Write the byte-order
245 // mark before anything else gets written to the file. Open the
246 // file for binary writing.
247 if (_wfopen_s(&m_reportfile, m_reportfilepath, L"wb") == EINVAL) {
248 // Couldn't open the file.
252 fwrite(&bom, sizeof(WCHAR), 1, m_reportfile);
253 setreportencoding(unicode);
257 // Open the file in text mode for ASCII output.
258 if (_wfopen_s(&m_reportfile, m_reportfilepath, L"w") == EINVAL) {
259 // Couldn't open the file.
263 setreportencoding(ascii);
266 if (m_reportfile == NULL) {
267 report(L"WARNING: Visual Leak Detector: Couldn't open report file for writing: %s\n"
268 L" The report will be sent to the debugger instead.\n", m_reportfilepath);
271 // Set the "report" function to write to the file.
272 setreportfile(m_reportfile, m_options & VLD_OPT_REPORT_TO_DEBUGGER);
275 if (m_options & VLD_OPT_SLOW_DEBUGGER_DUMP) {
276 // Insert a slight delay between messages sent to the debugger for
277 // output. (For working around a bug in VC6 where data sent to the
278 // debugger gets lost if it's sent too fast).
282 // This is highly unlikely to happen, but just in case, check to be sure
283 // we got a valid TLS index.
284 if (m_tlsindex == TLS_OUT_OF_INDEXES) {
285 report(L"ERROR: Visual Leak Detector could not be installed because thread local"
286 L" storage could not be allocated.");
290 // Initialize the symbol handler. We use it for obtaining source file/line
291 // number information and function names for the memory leak report.
292 symbolpath = buildsymbolsearchpath();
293 SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
294 if (!SymInitializeW(currentprocess, symbolpath, FALSE)) {
295 report(L"WARNING: Visual Leak Detector: The symbol handler failed to initialize (error=%lu).\n"
296 L" File and function names will probably not be available in call stacks.\n", GetLastError());
298 delete [] symbolpath;
300 // Patch into kernel32.dll's calls to LdrLoadDll so that VLD can
301 // dynamically attach to new modules loaded during runtime.
302 patchimport(kernel32, ntdll, "ntdll.dll", "LdrLoadDll", _LdrLoadDll);
304 // Attach Visual Leak Detector to every module loaded in the process.
305 newmodules = new ModuleSet;
306 newmodules->reserve(MODULESETRESERVE);
307 EnumerateLoadedModulesW64(currentprocess, addloadedmodule, newmodules);
308 attachtoloadedmodules(newmodules);
309 m_loadedmodules = newmodules;
310 m_status |= VLD_STATUS_INSTALLED;
312 report(L"Visual Leak Detector Version " VLDVERSION L" installed.\n");
313 if (m_status & VLD_STATUS_FORCE_REPORT_TO_FILE) {
314 // The report is being forced to a file. Let the human know why.
315 report(L"NOTE: Visual Leak Detector: Unicode-encoded reporting has been enabled, but the\n"
316 L" debugger is the only selected report destination. The debugger cannot display\n"
317 L" Unicode characters, so the report will also be sent to a file. If no file has\n"
318 L" been specified, the default file name is \"" VLD_DEFAULT_REPORT_FILE_NAME L"\".\n");
324 // Destructor - Detaches Visual Leak Detector from all modules loaded in the
325 // process, frees internally allocated resources, and generates the memory
328 VisualLeakDetector::~VisualLeakDetector ()
330 BlockMap::Iterator blockit;
334 vldblockheader_t *header;
336 HeapMap::Iterator heapit;
337 SIZE_T internalleaks = 0;
338 const char *leakfile = NULL;
339 WCHAR leakfilew [MAX_PATH];
341 ModuleSet::Iterator moduleit;
344 BOOL threadsactive= FALSE;
345 TlsSet::Iterator tlsit;
347 if (m_options & VLD_OPT_VLDOFF) {
348 // VLD has been turned off.
352 if (m_status & VLD_STATUS_INSTALLED) {
353 // Detach Visual Leak Detector from all previously attached modules.
354 EnumerateLoadedModulesW64(currentprocess, detachfrommodule, NULL);
356 // See if any threads that have ever entered VLD's code are still active.
357 EnterCriticalSection(&m_tlslock);
358 for (tlsit = m_tlsset->begin(); tlsit != m_tlsset->end(); ++tlsit) {
359 if ((*tlsit)->threadid == GetCurrentThreadId()) {
360 // Don't wait for the current thread to exit.
365 thread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, (*tlsit)->threadid);
366 if (thread == NULL) {
367 // Couldn't query this thread. We'll assume that it exited.
368 continue; // XXX should we check GetLastError()?
370 while (GetExitCodeThread(thread, &exitcode) == TRUE) {
371 if (exitcode != STILL_ACTIVE) {
372 // This thread exited.
376 // There is still at least one other thread running. The CRT
377 // will stomp it dead when it cleans up, which is not a
378 // graceful way for a thread to go down. Warn about this,
379 // and wait until the thread has exited so that we know it
380 // can't still be off running somewhere in VLD's code.
381 threadsactive = TRUE;
384 if ((sleepcount % 100) == 0) {
385 // Just in case this takes a long time, let the human
386 // know we are still here and alive.
387 report(L"Visual Leak Detector: Waiting for threads to terminate...\n");
392 LeaveCriticalSection(&m_tlslock);
394 if (m_status & VLD_STATUS_NEVER_ENABLED) {
395 // Visual Leak Detector started with leak detection disabled and
396 // it was never enabled at runtime. A lot of good that does.
397 report(L"WARNING: Visual Leak Detector: Memory leak detection was never enabled.\n");
400 // Generate a memory leak report for each heap in the process.
401 for (heapit = m_heapmap->begin(); heapit != m_heapmap->end(); ++heapit) {
402 heap = (*heapit).first;
407 if (m_leaksfound == 0) {
408 report(L"No memory leaks detected.\n");
411 report(L"Visual Leak Detector detected %lu memory leak", m_leaksfound);
412 report((m_leaksfound > 1) ? L"s.\n" : L".\n");
416 // Free resources used by the symbol handler.
417 if (!SymCleanup(currentprocess)) {
418 report(L"WARNING: Visual Leak Detector: The symbol handler failed to deallocate resources (error=%lu).\n",
422 // Free internally allocated resources used by the heapmap and blockmap.
423 for (heapit = m_heapmap->begin(); heapit != m_heapmap->end(); ++heapit) {
424 blockmap = &(*heapit).second->blockmap;
425 for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
426 delete (*blockit).second->callstack;
427 delete (*blockit).second;
433 // Free internally allocated resources used by the loaded module set.
434 for (moduleit = m_loadedmodules->begin(); moduleit != m_loadedmodules->end(); ++moduleit) {
435 delete (*moduleit).name;
436 delete (*moduleit).path;
438 delete m_loadedmodules;
440 // Free internally allocated resources used for thread local storage.
441 for (tlsit = m_tlsset->begin(); tlsit != m_tlsset->end(); ++tlsit) {
446 // Do a memory leak self-check.
447 header = vldblocklist;
449 // Doh! VLD still has an internally allocated block!
450 // This won't ever actually happen, right guys?... guys?
452 leakfile = header->file;
453 leakline = header->line;
454 mbstowcs_s(&count, leakfilew, MAX_PATH, leakfile, _TRUNCATE);
455 report(L"ERROR: Visual Leak Detector: Detected a memory leak internal to Visual Leak Detector!!\n");
456 report(L"---------- Block %ld at " ADDRESSFORMAT L": %u bytes ----------\n", header->serialnumber,
457 VLDBLOCKDATA(header), header->size);
458 report(L" Call Stack:\n");
459 report(L" %s (%d): Full call stack not available.\n", leakfilew, leakline);
460 if (m_maxdatadump != 0) {
462 if (m_options & VLD_OPT_UNICODE_REPORT) {
463 dumpmemoryw(VLDBLOCKDATA(header), (m_maxdatadump < header->size) ? m_maxdatadump : header->size);
466 dumpmemorya(VLDBLOCKDATA(header), (m_maxdatadump < header->size) ? m_maxdatadump : header->size);
470 header = header->next;
472 if (m_options & VLD_OPT_SELF_TEST) {
473 if ((internalleaks == 1) && (strcmp(leakfile, m_selftestfile) == 0) && (leakline == m_selftestline)) {
474 report(L"Visual Leak Detector passed the memory leak self-test.\n");
477 report(L"ERROR: Visual Leak Detector: Failed the memory leak self-test.\n");
481 if (threadsactive == TRUE) {
482 report(L"WARNING: Visual Leak Detector: Some threads appear to have not terminated normally.\n"
483 L" This could cause inaccurate leak detection results, including false positives.\n");
485 report(L"Visual Leak Detector is now exiting.\n");
488 // VLD failed to load properly.
492 HeapDestroy(vldheap);
494 DeleteCriticalSection(&imagelock);
495 DeleteCriticalSection(&m_loaderlock);
496 DeleteCriticalSection(&m_maplock);
497 DeleteCriticalSection(&m_moduleslock);
498 DeleteCriticalSection(&stackwalklock);
499 DeleteCriticalSection(&symbollock);
500 DeleteCriticalSection(&vldheaplock);
502 if (m_tlsindex != TLS_OUT_OF_INDEXES) {
506 if (m_reportfile != NULL) {
507 fclose(m_reportfile);
511 // _CoGetMalloc - Calls to CoGetMalloc are patched through to this function.
512 // This function returns a pointer to Visual Leak Detector's implementation
513 // of the IMalloc interface, instead of returning a pointer to the system
514 // implementation. This allows VLD's implementation of the IMalloc interface
515 // (which is basically a thin wrapper around the system implementation) to be
516 // invoked in place of the system implementation.
518 // - context (IN): Reserved; value must be 1.
520 // - imalloc (IN): Address of a pointer to receive the address of VLD's
521 // implementation of the IMalloc interface.
525 // Always returns S_OK.
527 HRESULT VisualLeakDetector::_CoGetMalloc (DWORD context, LPMALLOC *imalloc)
531 *imalloc = (LPMALLOC)&vld;
533 if (pCoGetMalloc == NULL) {
534 // This is the first call to this function. Link to the real
535 // CoGetMalloc and get a pointer to the system implementation of the
536 // IMalloc interface.
537 ole32 = GetModuleHandle(L"ole32.dll");
538 pCoGetMalloc = (CoGetMalloc_t)GetProcAddress(ole32, "CoGetMalloc");
539 pCoGetMalloc(context, &vld.m_imalloc);
545 // _CoTaskMemAlloc - Calls to CoTaskMemAlloc are patched through to this
546 // function. This function is just a wrapper around the real CoTaskMemAlloc
547 // that sets appropriate flags to be consulted when the memory is actually
548 // allocated by RtlAllocateHeap.
550 // - size (IN): Size of the memory block to allocate.
554 // Returns the value returned from CoTaskMemAlloc.
556 LPVOID VisualLeakDetector::_CoTaskMemAlloc (ULONG size)
561 tls_t *tls = vld.gettls();
563 if (tls->addrfp == 0x0) {
564 // This is the first call to enter VLD for the current allocation.
565 // Record the current frame pointer.
570 if (pCoTaskMemAlloc == NULL) {
571 // This is the first call to this function. Link to the real
573 ole32 = GetModuleHandle(L"ole32.dll");
574 pCoTaskMemAlloc = (CoTaskMemAlloc_t)GetProcAddress(ole32, "CoTaskMemAlloc");
577 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
578 block = pCoTaskMemAlloc(size);
580 // Reset thread local flags and variables for the next allocation.
582 tls->flags &= ~VLD_TLS_CRTALLOC;
587 // _CoTaskMemRealloc - Calls to CoTaskMemRealloc are patched through to this
588 // function. This function is just a wrapper around the real CoTaskMemRealloc
589 // that sets appropriate flags to be consulted when the memory is actually
590 // allocated by RtlAllocateHeap.
592 // - mem (IN): Pointer to the memory block to reallocate.
594 // - size (IN): Size, in bytes, of the block to reallocate.
598 // Returns the value returned from CoTaskMemRealloc.
600 LPVOID VisualLeakDetector::_CoTaskMemRealloc (LPVOID mem, ULONG size)
605 tls_t *tls = vld.gettls();
607 if (tls->addrfp == 0x0) {
608 // This is the first call to enter VLD for the current allocation.
609 // Record the current frame pointer.
614 if (pCoTaskMemRealloc == NULL) {
615 // This is the first call to this function. Link to the real
617 ole32 = GetModuleHandle(L"ole32.dll");
618 pCoTaskMemRealloc = (CoTaskMemRealloc_t)GetProcAddress(ole32, "CoTaskMemRealloc");
621 // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
622 block = pCoTaskMemRealloc(mem, size);
624 // Reset thread local flags and variables for the next allocation.
626 tls->flags &= ~VLD_TLS_CRTALLOC;
631 // _crt80d__calloc_dbg - Calls to _calloc_dbg from msvcr80d.dll are patched
632 // through to this function. This function is just a wrapper around the real
633 // _calloc_dbg that sets appropriate flags to be consulted when the memory is
634 // actually allocated by RtlAllocateHeap.
636 // - size (IN): The size, in bytes, of the memory block to be allocated.
638 // - type (IN): The CRT "use type" of the block to be allocated.
640 // - file (IN): The name of the file from which this function is being called.
642 // - line (IN): The line number, in the above file, at which this function is
647 // Returns the value returned by _calloc_dbg.
649 void* VisualLeakDetector::_crt80d__calloc_dbg (size_t num, size_t size, int type, const char *file, int line)
654 tls_t *tls = vld.gettls();
656 // _malloc_dbg is a CRT function and allocates from the CRT heap.
657 tls->flags |= VLD_TLS_CRTALLOC;
659 if (tls->addrfp == 0x0) {
660 // This is the first call to enter VLD for the current allocation.
661 // Record the current frame pointer.
666 if (pcrt80d__calloc_dbg == NULL) {
667 // This is the first call to this function. Link to the real
669 msvcr80d = GetModuleHandle(L"msvcr80d.dll");
670 pcrt80d__calloc_dbg = (_calloc_dbg_t)GetProcAddress(msvcr80d, "_calloc_dbg");
673 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
674 block = pcrt80d__calloc_dbg(num, size, type, file, line);
676 // Reset thread local flags and variables for the next allocation.
678 tls->flags &= ~VLD_TLS_CRTALLOC;
683 // _crt80d__malloc_dbg - Calls to _malloc_dbg from msvcr80d.dll are patched
684 // through to this function. This function is just a wrapper around the real
685 // _malloc_dbg that sets appropriate flags to be consulted when the memory is
686 // actually allocated by RtlAllocateHeap.
688 // - size (IN): The size, in bytes, of the memory block to be allocated.
690 // - type (IN): The CRT "use type" of the block to be allocated.
692 // - file (IN): The name of the file from which this function is being called.
694 // - line (IN): The line number, in the above file, at which this function is
699 // Returns the value returned by _malloc_dbg.
701 void* VisualLeakDetector::_crt80d__malloc_dbg (size_t size, int type, const char *file, int line)
706 tls_t *tls = vld.gettls();
708 // _malloc_dbg is a CRT function and allocates from the CRT heap.
709 tls->flags |= VLD_TLS_CRTALLOC;
711 if (tls->addrfp == 0x0) {
712 // This is the first call to enter VLD for the current allocation.
713 // Record the current frame pointer.
718 if (pcrt80d__malloc_dbg == NULL) {
719 // This is the first call to this function. Link to the real
721 msvcr80d = GetModuleHandle(L"msvcr80d.dll");
722 pcrt80d__malloc_dbg = (_malloc_dbg_t)GetProcAddress(msvcr80d, "_malloc_dbg");
725 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
726 block = pcrt80d__malloc_dbg(size, type, file, line);
728 // Reset thread local flags and variables for the next allocation.
730 tls->flags &= ~VLD_TLS_CRTALLOC;
735 // _crt80d__realloc_dbg - Calls to _realloc_dbg from msvcr80d.dll are patched
736 // through to this function. This function is just a wrapper around the real
737 // _realloc_dbg that sets appropriate flags to be consulted when the memory is
738 // actually allocated by RtlAllocateHeap.
740 // - mem (IN): Pointer to the memory block to be reallocated.
742 // - size (IN): The size of the memory block to reallocate.
744 // - type (IN): The CRT "use type" of the block to be reallocated.
746 // - file (IN): The name of the file from which this function is being called.
748 // - line (IN): The line number, in the above filel, at which this function is
753 // Returns the value returned by _realloc_dbg.
755 void* VisualLeakDetector::_crt80d__realloc_dbg (void *mem, size_t size, int type, const char *file, int line)
760 tls_t *tls = vld.gettls();
762 // _realloc_dbg is a CRT function and allocates from the CRT heap.
763 tls->flags |= VLD_TLS_CRTALLOC;
765 if (tls->addrfp == 0x0) {
766 // This is the first call to enter VLD for the current allocation.
767 // Record the current frame pointer.
772 if (pcrt80d__realloc_dbg == NULL) {
773 // This is the first call to this function. Link to the real
775 msvcr80d = GetModuleHandle(L"msvcr80d.dll");
776 pcrt80d__realloc_dbg = (_realloc_dbg_t)GetProcAddress(msvcr80d, "_realloc_dbg");
779 // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
780 block = pcrt80d__realloc_dbg(mem, size, type, file, line);
782 // Reset thread local flags and variables for the next allocation.
784 tls->flags &= ~VLD_TLS_CRTALLOC;
789 // _crt80d__scalar_new_dbg - Calls to the CRT's debug scalar new operator from
790 // msvcr80d.dll are patched through to this function. This function is just a
791 // wrapper around the real CRT debug scalar new operator that sets appropriate
792 // flags to be consulted when the memory is actually allocated by
795 // - size (IN): The size, in bytes, of the memory block to be allocated.
797 // - type (IN): The CRT "use type" of the block to be allocated.
799 // - file (IN): The name of the file from which this function is being called.
801 // - line (IN): The line number, in the above file, at which this function is
806 // Returns the value returned by the CRT debug scalar new operator.
808 void* VisualLeakDetector::_crt80d__scalar_new_dbg (unsigned int size, int type, const char *file, int line)
813 tls_t *tls = vld.gettls();
815 // The debug new operator is a CRT function and allocates from the CRT heap.
816 tls->flags |= VLD_TLS_CRTALLOC;
818 if (tls->addrfp == 0x0) {
819 // This is the first call to enter VLD for the current allocation.
820 // Record the current frame pointer.
825 if (pcrt80d__scalar_new_dbg == NULL) {
826 // This is the first call to this function. Link to the real CRT debug
828 msvcr80d = GetModuleHandle(L"msvcr80d.dll");
829 pcrt80d__scalar_new_dbg = (crt_new_dbg_t)GetProcAddress(msvcr80d, "??2@YAPAXIHPBDH@Z");
832 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
833 block = pcrt80d__scalar_new_dbg(size, type, file, line);
835 // Reset thread local flags and variables for the next allocation.
837 tls->flags &= ~VLD_TLS_CRTALLOC;
842 // _crt80d__vector_new_dbg - Calls to the CRT's debug vector new operator from
843 // msvcr80d.dll are patched through to this function. This function is just a
844 // wrapper around the real CRT debug vector new operator that sets appropriate
845 // flags to be consulted when the memory is actually allocated by
848 // - size (IN): The size, in bytes, of the memory block to be allocated.
850 // - type (IN): The CRT "use type" of the block to be allocated.
852 // - file (IN): The name of the file from which this function is being called.
854 // - line (IN): The line number, in the above file, at which this function is
859 // Returns the value returned by the CRT debug vector new operator.
861 void* VisualLeakDetector::_crt80d__vector_new_dbg (unsigned int size, int type, const char *file, int line)
866 tls_t *tls = vld.gettls();
868 // The debug new operator is a CRT function and allocates from the CRT heap.
869 tls->flags |= VLD_TLS_CRTALLOC;
871 if (tls->addrfp == 0x0) {
872 // This is the first call to enter VLD for the current allocation.
873 // Record the current frame pointer.
878 if (pcrt80d__vector_new_dbg == NULL) {
879 // This is the first call to this function. Link to the real CRT debug
881 msvcr80d = GetModuleHandle(L"msvcr80d.dll");
882 pcrt80d__vector_new_dbg = (crt_new_dbg_t)GetProcAddress(msvcr80d, "??_U@YAPAXIHPBDH@Z");
885 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
886 block = pcrt80d__vector_new_dbg(size, type, file, line);
888 // Reset thread local flags and variables for the next allocation.
890 tls->flags &= ~VLD_TLS_CRTALLOC;
895 // _crt80d_calloc - Calls to calloc from msvcr80d.dll are patched through to
896 // this function. This function is just a wrapper around the real calloc that
897 // sets appropriate flags to be consulted when the memory is actually
898 // allocated by RtlAllocateHeap.
900 // - num (IN): The number of blocks, of size 'size', to be allocated.
902 // - size (IN): The size, in bytes, of the memory block to be allocated.
906 // Returns the valued returned from calloc.
908 void* VisualLeakDetector::_crt80d_calloc (size_t num, size_t size)
913 tls_t *tls = vld.gettls();
915 // malloc is a CRT function and allocates from the CRT heap.
916 tls->flags |= VLD_TLS_CRTALLOC;
918 if (tls->addrfp == 0x0) {
919 // This is the first call to enter VLD for the current allocation.
920 // Record the current frame pointer.
925 if (pcrt80d_calloc == NULL) {
926 // This is the first call to this function. Link to the real malloc.
927 msvcr80d = GetModuleHandle(L"msvcr80d.dll");
928 pcrt80d_calloc = (calloc_t)GetProcAddress(msvcr80d, "calloc");
931 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
932 block = pcrt80d_calloc(num, size);
934 // Reset thread local flags and variables for the next allocation.
936 tls->flags &= ~VLD_TLS_CRTALLOC;
941 // _crt80d_malloc - Calls to malloc from msvcr80d.dll are patched through to
942 // this function. This function is just a wrapper around the real malloc that
943 // sets appropriate flags to be consulted when the memory is actually
944 // allocated by RtlAllocateHeap.
946 // - size (IN): The size, in bytes, of the memory block to be allocated.
950 // Returns the valued returned from malloc.
952 void* VisualLeakDetector::_crt80d_malloc (size_t size)
957 tls_t *tls = vld.gettls();
959 // malloc is a CRT function and allocates from the CRT heap.
960 tls->flags |= VLD_TLS_CRTALLOC;
962 if (tls->addrfp == 0x0) {
963 // This is the first call to enter VLD for the current allocation.
964 // Record the current frame pointer.
969 if (pcrt80d_malloc == NULL) {
970 // This is the first call to this function. Link to the real malloc.
971 msvcr80d = GetModuleHandle(L"msvcr80d.dll");
972 pcrt80d_malloc = (malloc_t)GetProcAddress(msvcr80d, "malloc");
975 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
976 block = pcrt80d_malloc(size);
978 // Reset thread local flags and variables for the next allocation.
980 tls->flags &= ~VLD_TLS_CRTALLOC;
985 // _crt80d_realloc - Calls to realloc from msvcr80d.dll are patched through to
986 // this function. This function is just a wrapper around the real realloc that
987 // sets appropriate flags to be consulted when the memory is actually
988 // allocated by RtlAllocateHeap.
990 // - mem (IN): Pointer to the memory block to reallocate.
992 // - size (IN): Size of the memory block to reallocate.
996 // Returns the value returned from realloc.
998 void* VisualLeakDetector::_crt80d_realloc (void *mem, size_t size)
1003 tls_t *tls = vld.gettls();
1005 // realloc is a CRT function and allocates from the CRT heap.
1006 tls->flags |= VLD_TLS_CRTALLOC;
1008 if (tls->addrfp == 0x0) {
1009 // This is the first call to enter VLD for the current allocation.
1010 // Record the current frame pointer.
1015 if (pcrt80d_realloc == NULL) {
1016 // This is the first call to this function. Link to the real realloc.
1017 msvcr80d = GetModuleHandle(L"msvcr80d.dll");
1018 pcrt80d_realloc = (realloc_t)GetProcAddress(msvcr80d, "realloc");
1021 // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
1022 block = pcrt80d_realloc(mem, size);
1024 // Reset thread local flags and variables for the next allocation.
1026 tls->flags &= ~VLD_TLS_CRTALLOC;
1031 // _crt80d_scalar_new - Calls to the CRT's scalar new operator from msvcr80d.dll
1032 // are patched through to this function. This function is just a wrapper
1033 // around the real CRT scalar new operator that sets appropriate flags to be
1034 // consulted when the memory is actually allocated by RtlAllocateHeap.
1036 // - size (IN): The size, in bytes, of the memory block to be allocated.
1040 // Returns the value returned by the CRT scalar new operator.
1042 void* VisualLeakDetector::_crt80d_scalar_new (unsigned int size)
1047 tls_t *tls = vld.gettls();
1049 // The new operator is a CRT function and allocates from the CRT heap.
1050 tls->flags |= VLD_TLS_CRTALLOC;
1052 if (tls->addrfp == 0x0) {
1053 // This is the first call to enter VLD for the current allocation.
1054 // Record the current frame pointer.
1059 if (pcrt80d_scalar_new == NULL) {
1060 // This is the first call to this function. Link to the real CRT new
1062 msvcr80d = GetModuleHandle(L"msvcr80d.dll");
1063 pcrt80d_scalar_new = (new_t)GetProcAddress(msvcr80d, "??2@YAPAXI@Z");
1066 // Do tha allocation. The block will be mapped by _RtlAllocateHeap.
1067 block = pcrt80d_scalar_new(size);
1069 // Reset thread local flags and variables for the next allocation.
1071 tls->flags &= ~VLD_TLS_CRTALLOC;
1076 // _crt80d_vector_new - Calls to the CRT's vector new operator from msvcr80d.dll
1077 // are patched through to this function. This function is just a wrapper
1078 // around the real CRT vector new operator that sets appropriate flags to be
1079 // consulted when the memory is actually allocated by RtlAllocateHeap.
1081 // - size (IN): The size, in bytes, of the memory block to be allocated.
1085 // Returns the value returned by the CRT vector new operator.
1087 void* VisualLeakDetector::_crt80d_vector_new (unsigned int size)
1092 tls_t *tls = vld.gettls();
1094 // The new operator is a CRT function and allocates from the CRT heap.
1095 tls->flags |= VLD_TLS_CRTALLOC;
1097 if (tls->addrfp == 0x0) {
1098 // This is the first call to enter VLD for the current allocation.
1099 // Record the current frame pointer.
1104 if (pcrt80d_vector_new == NULL) {
1105 // This is the first call to this function. Link to the real CRT new
1107 msvcr80d = GetModuleHandle(L"msvcr80d.dll");
1108 pcrt80d_vector_new = (new_t)GetProcAddress(msvcr80d, "??_U@YAPAXI@Z");
1111 // Do tha allocation. The block will be mapped by _RtlAllocateHeap.
1112 block = pcrt80d_vector_new(size);
1114 // Reset thread local flags and variables for the next allocation.
1116 tls->flags &= ~VLD_TLS_CRTALLOC;
1121 // _crtd__calloc_dbg - Calls to _calloc_dbg from msvcrtd.dll are patched through
1122 // to this function. This function is just a wrapper around the real
1123 // _calloc_dbg that sets appropriate flags to be consulted when the memory is
1124 // actually allocated by RtlAllocateHeap.
1126 // - num (IN): The number of blocks, of size 'size', to be allocated.
1128 // - size (IN): The size, in bytes, of the memory block to be allocated.
1130 // - type (IN): The CRT "use type" of the block to be allocated.
1132 // - file (IN): The name of the file from which this function is being called.
1134 // - line (IN): The line number, in the above file, at which this function is
1139 // Returns the value returned by _calloc_dbg.
1141 void* VisualLeakDetector::_crtd__calloc_dbg (size_t num, size_t size, int type, const char *file, int line)
1146 tls_t *tls = vld.gettls();
1148 // _malloc_dbg is a CRT function and allocates from the CRT heap.
1149 tls->flags |= VLD_TLS_CRTALLOC;
1151 if (tls->addrfp == 0x0) {
1152 // This is the first call to enter VLD for the current allocation.
1153 // Record the current frame pointer.
1158 if (pcrtd__calloc_dbg == NULL) {
1159 // This is the first call to this function. Link to the real
1161 msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1162 pcrtd__calloc_dbg = (_calloc_dbg_t)GetProcAddress(msvcrtd, "_calloc_dbg");
1165 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1166 block = pcrtd__calloc_dbg(num, size, type, file, line);
1168 // Reset thread local flags and variables for the next allocation.
1170 tls->flags &= ~VLD_TLS_CRTALLOC;
1175 // _crtd__malloc_dbg - Calls to _malloc_dbg from msvcrtd.dll are patched through
1176 // to this function. This function is just a wrapper around the real
1177 // _malloc_dbg that sets appropriate flags to be consulted when the memory is
1178 // actually allocated by RtlAllocateHeap.
1180 // - size (IN): The size, in bytes, of the memory block to be allocated.
1182 // - type (IN): The CRT "use type" of the block to be allocated.
1184 // - file (IN): The name of the file from which this function is being called.
1186 // - line (IN): The line number, in the above file, at which this function is
1191 // Returns the value returned by _malloc_dbg.
1193 void* VisualLeakDetector::_crtd__malloc_dbg (size_t size, int type, const char *file, int line)
1198 tls_t *tls = vld.gettls();
1200 // _malloc_dbg is a CRT function and allocates from the CRT heap.
1201 tls->flags |= VLD_TLS_CRTALLOC;
1203 if (tls->addrfp == 0x0) {
1204 // This is the first call to enter VLD for the current allocation.
1205 // Record the current frame pointer.
1210 if (pcrtd__malloc_dbg == NULL) {
1211 // This is the first call to this function. Link to the real
1213 msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1214 pcrtd__malloc_dbg = (_malloc_dbg_t)GetProcAddress(msvcrtd, "_malloc_dbg");
1217 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1218 block = pcrtd__malloc_dbg(size, type, file, line);
1220 // Reset thread local flags and variables for the next allocation.
1222 tls->flags &= ~VLD_TLS_CRTALLOC;
1227 // _crtd__realloc_dbg - Calls to _realloc_dbg from msvcrtd.dll are patched
1228 // through to this function. This function is just a wrapper around the real
1229 // _realloc_dbg that sets appropriate flags to be consulted when the memory is
1230 // actually allocated by RtlAllocateHeap.
1232 // - mem (IN): Pointer to the memory block to be reallocated.
1234 // - size (IN): The size of the memory block to reallocate.
1236 // - type (IN): The CRT "use type" of the block to be reallocated.
1238 // - file (IN): The name of the file from which this function is being called.
1240 // - line (IN): The line number, in the above filel, at which this function is
1245 // Returns the value returned by _realloc_dbg.
1247 void* VisualLeakDetector::_crtd__realloc_dbg (void *mem, size_t size, int type, const char *file, int line)
1252 tls_t *tls = vld.gettls();
1254 // _realloc_dbg is a CRT function and allocates from the CRT heap.
1255 tls->flags |= VLD_TLS_CRTALLOC;
1257 if (tls->addrfp == 0x0) {
1258 // This is the first call to enter VLD for the current allocation.
1259 // Record the current frame pointer.
1264 if (pcrtd__realloc_dbg == NULL) {
1265 // This is the first call to this function. Link to the real
1267 msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1268 pcrtd__realloc_dbg = (_realloc_dbg_t)GetProcAddress(msvcrtd, "_realloc_dbg");
1271 // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
1272 block = pcrtd__realloc_dbg(mem, size, type, file, line);
1274 // Reset thread local flags and variables for the next allocation.
1276 tls->flags &= ~VLD_TLS_CRTALLOC;
1281 // _crtd__scalar_new_dbg - Calls to the CRT's debug scalar new operator from
1282 // msvcrtd.dll are patched through to this function. This function is just a
1283 // wrapper around the real CRT debug scalar new operator that sets appropriate
1284 // flags to be consulted when the memory is actually allocated by
1287 // - size (IN): The size, in bytes, of the memory block to be allocated.
1289 // - type (IN): The CRT "use type" of the block to be allocated.
1291 // - file (IN): The name of the file from which this function is being called.
1293 // - line (IN): The line number, in the above file, at which this function is
1298 // Returns the value returned by the CRT debug scalar new operator.
1300 void* VisualLeakDetector::_crtd__scalar_new_dbg (unsigned int size, int type, const char *file, int line)
1305 tls_t *tls = vld.gettls();
1307 // The debug new operator is a CRT function and allocates from the CRT heap.
1308 tls->flags |= VLD_TLS_CRTALLOC;
1310 if (tls->addrfp == 0x0) {
1311 // This is the first call to enter VLD for the current allocation.
1312 // Record the current frame pointer.
1317 if (pcrtd__scalar_new_dbg == NULL) {
1318 // This is the first call to this function. Link to the real CRT debug
1320 msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1321 pcrtd__scalar_new_dbg = (crt_new_dbg_t)GetProcAddress(msvcrtd, "??2@YAPAXIHPBDH@Z");
1324 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1325 block = pcrtd__scalar_new_dbg(size, type, file, line);
1327 // Reset thread local flags and variables for the next allocation.
1329 tls->flags &= ~VLD_TLS_CRTALLOC;
1334 // _crtd_calloc - Calls to calloc from msvcrtd.dll are patched through to this
1335 // function. This function is just a wrapper around the real calloc that sets
1336 // appropriate flags to be consulted when the memory is actually allocated by
1339 // - num (IN): The number of blocks, of size 'size', to be allocated.
1341 // - size (IN): The size, in bytes, of the memory block to be allocated.
1345 // Returns the valued returned from calloc.
1347 void* VisualLeakDetector::_crtd_calloc (size_t num, size_t size)
1352 tls_t *tls = vld.gettls();
1354 // malloc is a CRT function and allocates from the CRT heap.
1355 tls->flags |= VLD_TLS_CRTALLOC;
1357 if (tls->addrfp == 0x0) {
1358 // This is the first call to enter VLD for the current allocation.
1359 // Record the current frame pointer.
1364 if (pcrtd_calloc == NULL) {
1365 // This is the first call to this function. Link to the real malloc.
1366 msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1367 pcrtd_calloc = (calloc_t)GetProcAddress(msvcrtd, "calloc");
1370 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1371 block = pcrtd_calloc(num, size);
1373 // Reset thread local flags and variables for the next allocation.
1375 tls->flags &= ~VLD_TLS_CRTALLOC;
1380 // _crtd_malloc - Calls to malloc from msvcrtd.dll are patched through to this
1381 // function. This function is just a wrapper around the real malloc that sets
1382 // appropriate flags to be consulted when the memory is actually allocated by
1385 // - size (IN): The size, in bytes, of the memory block to be allocated.
1389 // Returns the valued returned from malloc.
1391 void* VisualLeakDetector::_crtd_malloc (size_t size)
1396 tls_t *tls = vld.gettls();
1398 // malloc is a CRT function and allocates from the CRT heap.
1399 tls->flags |= VLD_TLS_CRTALLOC;
1401 if (tls->addrfp == 0x0) {
1402 // This is the first call to enter VLD for the current allocation.
1403 // Record the current frame pointer.
1408 if (pcrtd_malloc == NULL) {
1409 // This is the first call to this function. Link to the real malloc.
1410 msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1411 pcrtd_malloc = (malloc_t)GetProcAddress(msvcrtd, "malloc");
1414 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1415 block = pcrtd_malloc(size);
1417 // Reset thread local flags and variables for the next allocation.
1419 tls->flags &= ~VLD_TLS_CRTALLOC;
1424 // _crtd_realloc - Calls to realloc from msvcrtd.dll are patched through to this
1425 // function. This function is just a wrapper around the real realloc that sets
1426 // appropriate flags to be consulted when the memory is actually allocated by
1429 // - mem (IN): Pointer to the memory block to reallocate.
1431 // - size (IN): Size of the memory block to reallocate.
1435 // Returns the value returned from realloc.
1437 void* VisualLeakDetector::_crtd_realloc (void *mem, size_t size)
1442 tls_t *tls = vld.gettls();
1444 // realloc is a CRT function and allocates from the CRT heap.
1445 tls->flags |= VLD_TLS_CRTALLOC;
1447 if (tls->addrfp == 0x0) {
1448 // This is the first call to enter VLD for the current allocation.
1449 // Record the current frame pointer.
1454 if (pcrtd_realloc == NULL) {
1455 // This is the first call to this function. Link to the real realloc.
1456 msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1457 pcrtd_realloc = (realloc_t)GetProcAddress(msvcrtd, "realloc");
1460 // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
1461 block = pcrtd_realloc(mem, size);
1463 // Reset thread local flags and variables for the next allocation.
1465 tls->flags &= ~VLD_TLS_CRTALLOC;
1470 // _crtd_scalar_new - Calls to the CRT's scalar new operator from msvcrtd.dll
1471 // are patched through to this function. This function is just a wrapper
1472 // around the real CRT scalar new operator that sets appropriate flags to be
1473 // consulted when the memory is actually allocated by RtlAllocateHeap.
1475 // - size (IN): The size, in bytes, of the memory block to be allocated.
1479 // Returns the value returned by the CRT scalar new operator.
1481 void* VisualLeakDetector::_crtd_scalar_new (unsigned int size)
1486 tls_t *tls = vld.gettls();
1488 // The new operator is a CRT function and allocates from the CRT heap.
1489 tls->flags |= VLD_TLS_CRTALLOC;
1491 if (tls->addrfp == 0x0) {
1492 // This is the first call to enter VLD for the current allocation.
1493 // Record the current frame pointer.
1498 if (pcrtd_scalar_new == NULL) {
1499 // This is the first call to this function. Link to the real CRT new
1501 msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1502 pcrtd_scalar_new = (new_t)GetProcAddress(msvcrtd, "??2@YAPAXI@Z");
1505 // Do tha allocation. The block will be mapped by _RtlAllocateHeap.
1506 block = pcrtd_scalar_new(size);
1508 // Reset thread local flags and variables for the next allocation.
1510 tls->flags &= ~VLD_TLS_CRTALLOC;
1515 // _GetProcAddress - Calls to GetProcAddress are patched through to this
1516 // function. If the requested function is a function that has been patched
1517 // through to one of VLD's handlers, then the address of VLD's handler
1518 // function is returned instead of the real address. Otherwise, this
1519 // function is just a wrapper around the real GetProcAddress.
1521 // - module (IN): Handle (base address) of the module from which to retrieve
1522 // the address of an exported function.
1524 // - procname (IN): ANSI string containing the name of the exported function
1525 // whose address is to be retrieved.
1529 // Returns a pointer to the requested function, or VLD's replacement for
1530 // the function, if there is a replacement function.
1532 FARPROC VisualLeakDetector::_GetProcAddress (HMODULE module, LPCSTR procname)
1534 patchentry_t *entry;
1536 UINT tablesize = sizeof(vld.m_patchtable) / sizeof(patchentry_t);
1538 // See if there is an entry in the patch table that matches the requested
1540 for (index = 0; index < tablesize; index++) {
1541 entry = &vld.m_patchtable[index];
1542 if ((entry->modulebase == 0x0) || ((HMODULE)entry->modulebase != module)) {
1543 // This patch table entry is for a different module.
1547 // This patch table entry is for the specified module. If the requested
1548 // import's name matches the entry's import name (or ordinal), then
1549 // return the address of the replacement instead of the address of the
1551 if ((SIZE_T)entry->importname < (SIZE_T)vld.m_vldbase) {
1552 // This entry's import name is not a valid pointer to data in
1553 // vld.dll. It must be an ordinal value.
1554 if ((UINT)entry->importname == (UINT)procname) {
1555 return (FARPROC)entry->replacement;
1559 if (strcmp(entry->importname, procname) == 0) {
1560 return (FARPROC)entry->replacement;
1565 // The requested function is not a patched function. Just return the real
1566 // address of the requested function.
1567 return GetProcAddress(module, procname);
1570 // _HeapCreate - Calls to HeapCreate are patched through to this function. This
1571 // function is just a wrapper around the real HeapCreate that calls VLD's heap
1572 // creation tracking function after the heap has been created.
1574 // - options (IN): Heap options.
1576 // - initsize (IN): Initial size of the heap.
1578 // - maxsize (IN): Maximum size of the heap.
1582 // Returns the value returned by HeapCreate.
1584 HANDLE VisualLeakDetector::_HeapCreate (DWORD options, SIZE_T initsize, SIZE_T maxsize)
1586 DWORD64 displacement;
1588 SYMBOL_INFO *functioninfo;
1590 HeapMap::Iterator heapit;
1592 BYTE symbolbuffer [sizeof(SYMBOL_INFO) + (MAXSYMBOLNAMELENGTH * sizeof(WCHAR)) - 1] = { 0 };
1595 // Get the return address within the calling function.
1597 ra = *((SIZE_T*)fp + 1);
1600 heap = HeapCreate(options, initsize, maxsize);
1602 // Map the created heap handle to a new block map.
1605 // Try to get the name of the function containing the return address.
1606 functioninfo = (SYMBOL_INFO*)&symbolbuffer;
1607 functioninfo->SizeOfStruct = sizeof(SYMBOL_INFO);
1608 functioninfo->MaxNameLen = MAXSYMBOLNAMELENGTH;
1609 EnterCriticalSection(&symbollock);
1610 symfound = SymFromAddrW(currentprocess, ra, &displacement, functioninfo);
1611 LeaveCriticalSection(&symbollock);
1612 if (symfound == TRUE) {
1613 if (wcscmp(L"_heap_init", functioninfo->Name) == 0) {
1614 // HeapCreate was called by _heap_init. This is a static CRT heap.
1615 EnterCriticalSection(&vld.m_maplock);
1616 heapit = vld.m_heapmap->find(heap);
1617 assert(heapit != vld.m_heapmap->end());
1618 (*heapit).second->flags |= VLD_HEAP_CRT;
1619 LeaveCriticalSection(&vld.m_maplock);
1626 // _HeapDestroy - Calls to HeapDestroy are patched through to this function.
1627 // This function is just a wrapper around the real HeapDestroy that calls
1628 // VLD's heap destruction tracking function after the heap has been destroyed.
1630 // - heap (IN): Handle to the heap to be destroyed.
1634 // Returns the valued returned by HeapDestroy.
1636 BOOL VisualLeakDetector::_HeapDestroy (HANDLE heap)
1638 // After this heap is destroyed, the heap's address space will be unmapped
1639 // from the process's address space. So, we'd better generate a leak report
1640 // for this heap now, while we can still read from the memory blocks
1642 vld.reportleaks(heap);
1644 vld.unmapheap(heap);
1646 return HeapDestroy(heap);
1649 // _LdrLoadDll - Calls to LdrLoadDll are patched through to this function. This
1650 // function invokes the real LdrLoadDll and then re-attaches VLD to all
1651 // modules loaded in the process after loading of the new DLL is complete.
1652 // All modules must be re-enumerated because the explicit load of the
1653 // specified module may result in the implicit load of one or more additional
1654 // modules which are dependencies of the specified module.
1656 // - searchpath (IN): The path to use for searching for the specified module to
1659 // - flags (IN): Pointer to action flags.
1661 // - modulename (IN): Pointer to a unicodestring_t structure specifying the
1662 // name of the module to be loaded.
1664 // - modulehandle (OUT): Address of a HANDLE to receive the newly loaded
1669 // Returns the value returned by LdrLoadDll.
1671 NTSTATUS VisualLeakDetector::_LdrLoadDll (LPWSTR searchpath, PDWORD flags, unicodestring_t *modulename,
1672 PHANDLE modulehandle)
1674 ModuleSet::Iterator moduleit;
1675 ModuleSet *newmodules;
1676 ModuleSet *oldmodules;
1680 status = LdrLoadDll(searchpath, flags, modulename, modulehandle);
1682 if (STATUS_SUCCESS == status) {
1683 // Create a new set of all loaded modules, including any newly loaded
1685 newmodules = new ModuleSet;
1686 newmodules->reserve(MODULESETRESERVE);
1687 EnterCriticalSection(&vld.m_loaderlock);
1688 EnumerateLoadedModulesW64(currentprocess, addloadedmodule, newmodules);
1689 LeaveCriticalSection(&vld.m_loaderlock);
1691 // Attach to all modules included in the set.
1692 vld.attachtoloadedmodules(newmodules);
1694 // Start using the new set of loaded modules.
1695 EnterCriticalSection(&vld.m_moduleslock);
1696 oldmodules = vld.m_loadedmodules;
1697 vld.m_loadedmodules = newmodules;
1698 LeaveCriticalSection(&vld.m_moduleslock);
1700 // Free resources used by the old module list.
1701 for (moduleit = oldmodules->begin(); moduleit != oldmodules->end(); ++moduleit) {
1702 delete (*moduleit).name;
1703 delete (*moduleit).path;
1711 // _mfc42d__scalar_new_dbg - Calls to the MFC debug scalar new operator from
1712 // mfc42d.dll are patched through to this function. This function is just a
1713 // wrapper around the real MFC debug scalar new operator that sets appropriate
1714 // flags to be consulted when the memory is actually allocated by
1717 // - size (IN): The size, in bytes, of the memory block to be allocated.
1719 // - file (IN): The name of the file from which this function is being called.
1721 // - line (IN): The line number, in the above file, at which this function is
1726 // Returns the value returned by the MFC debug scalar new operator.
1728 void* VisualLeakDetector::_mfc42d__scalar_new_dbg (unsigned int size, const char *file, int line)
1733 tls_t *tls = vld.gettls();
1735 // The MFC new operators are CRT-based and allocate from the CRT heap.
1736 tls->flags |= VLD_TLS_CRTALLOC;
1738 if (tls->addrfp == 0x0) {
1739 // This is the first call to enter VLD for the current allocation.
1740 // Record the current frame pointer.
1745 if (pmfc42d__scalar_new_dbg == NULL) {
1746 // This is the first call to this function. Link to the real MFC debug
1748 mfc42d = GetModuleHandle(L"mfc42d.dll");
1749 pmfc42d__scalar_new_dbg = (mfc_new_dbg_t)GetProcAddress(mfc42d, (LPCSTR)714);
1752 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1753 block = pmfc42d__scalar_new_dbg(size, file, line);
1755 // Reset thread local flags and variables for the next allocation.
1757 tls->flags &= ~VLD_TLS_CRTALLOC;
1762 // _mfc42d_scalar_new - Calls to the MFC scalar new operator from mfc42d.dll are
1763 // patched through to this function. This function is just a wrapper around
1764 // the real MFC scalar new operator that sets appropriate flags to be
1765 // consulted when the memory is actually allocated by RtlAllocateHeap.
1767 // - size (IN): The size, in bytes, of the memory block to be allocated.
1771 // Returns the value returned by the MFC scalar new operator.
1773 void* VisualLeakDetector::_mfc42d_scalar_new (unsigned int size)
1778 tls_t *tls = vld.gettls();
1780 // The MFC new operators are CRT-based and allocate from the CRT heap.
1781 tls->flags |= VLD_TLS_CRTALLOC;
1783 if (tls->addrfp == 0x0) {
1784 // This is the first call to enter VLD for the current allocation.
1785 // Record the current frame pointer.
1790 if (pmfc42d_scalar_new == NULL) {
1791 // This is the first call to this function. Link to the real MFC new
1793 mfc42d = GetModuleHandle(L"mfc42d.dll");
1794 pmfc42d_scalar_new = (new_t)GetProcAddress(mfc42d, (LPCSTR)711);
1797 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1798 block = pmfc42d_scalar_new(size);
1800 // Reset thread local flags and variables for the next allocation.
1802 tls->flags &= ~VLD_TLS_CRTALLOC;
1807 // _mfc80d__scalar_new_dbg - Calls to the MFC debug scalar new operator from
1808 // mfc80d.dll are patched through to this function. This function is just a
1809 // wrapper around the real MFC debug scalar new operator that sets appropriate
1810 // flags to be consulted when the memory is actually allocated by
1813 // - size (IN): The size, in bytes, of the memory block to be allocated.
1815 // - file (IN): The name of the file from which this function is being called.
1817 // - line (IN): The line number, in the above file, at which this function is
1822 // Returns the value returned by the MFC debug scalar new operator.
1824 void* VisualLeakDetector::_mfc80d__scalar_new_dbg (unsigned int size, const char *file, int line)
1829 tls_t *tls = vld.gettls();
1831 // The MFC new operators are CRT-based and allocate from the CRT heap.
1832 tls->flags |= VLD_TLS_CRTALLOC;
1834 if (tls->addrfp == 0x0) {
1835 // This is the first call to enter VLD for the current allocation.
1836 // Record the current frame pointer.
1841 if (pmfc80d__scalar_new_dbg == NULL) {
1842 // This is the first call to this function. Link to the real MFC debug
1844 mfc80d = GetModuleHandle(L"mfc80d.dll");
1845 pmfc80d__scalar_new_dbg = (mfc_new_dbg_t)GetProcAddress(mfc80d, (LPCSTR)895);
1848 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1849 block = pmfc80d__scalar_new_dbg(size, file, line);
1851 // Reset thread local flags and variables for the next allocation.
1853 tls->flags &= ~VLD_TLS_CRTALLOC;
1858 // _mfc80d__vector_new_dbg - Calls to the MFC debug vector new operator from
1859 // mfc80d.dll are patched through to this function. This function is just a
1860 // wrapper around the real MFC debug vector new operator that sets appropriate
1861 // flags to be consulted when the memory is actually allocated by
1864 // - size (IN): The size, in bytes, of the memory block to be allocated.
1866 // - file (IN): The name of the file from which this function is being called.
1868 // - line (IN): The line number, in the above file, at which this function is
1873 // Returns the value returned by the MFC debug vector new operator.
1875 void* VisualLeakDetector::_mfc80d__vector_new_dbg (unsigned int size, const char *file, int line)
1880 tls_t *tls = vld.gettls();
1882 // The MFC new operators are CRT-based and allocate from the CRT heap.
1883 tls->flags |= VLD_TLS_CRTALLOC;
1885 if (tls->addrfp == 0x0) {
1886 // This is the first call to enter VLD for the current allocation.
1887 // Record the current frame pointer.
1892 if (pmfc80d__vector_new_dbg == NULL) {
1893 // This is the first call to this function. Link to the real MFC debug
1895 mfc80d = GetModuleHandle(L"mfc80d.dll");
1896 pmfc80d__vector_new_dbg = (mfc_new_dbg_t)GetProcAddress(mfc80d, (LPCSTR)269);
1899 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1900 block = pmfc80d__vector_new_dbg(size, file, line);
1902 // Reset thread local flags and variables for the next allocation.
1904 tls->flags &= ~VLD_TLS_CRTALLOC;
1909 // _mfc80d_scalar_new - Calls to the MFC scalar new operator from mfc80d.dll are
1910 // patched through to this function. This function is just a wrapper around
1911 // the real MFC scalar new operator that sets appropriate flags to be
1912 // consulted when the memory is actually allocated by RtlAllocateHeap.
1914 // - size (IN): The size, in bytes, of the memory block to be allocated.
1918 // Returns the value returned by the MFC scalar new operator.
1920 void* VisualLeakDetector::_mfc80d_scalar_new (unsigned int size)
1925 tls_t *tls = vld.gettls();
1927 // The MFC new operators are CRT-based and allocate from the CRT heap.
1928 tls->flags |= VLD_TLS_CRTALLOC;
1930 if (tls->addrfp == 0x0) {
1931 // This is the first call to enter VLD for the current allocation.
1932 // Record the current frame pointer.
1937 if (pmfc80d_scalar_new == NULL) {
1938 // This is the first call to this function. Link to the real MFC 8.0 new
1940 mfc80d = GetModuleHandle(L"mfc80d.dll");
1941 pmfc80d_scalar_new = (new_t)GetProcAddress(mfc80d, (LPCSTR)893);
1944 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1945 block = pmfc80d_scalar_new(size);
1947 // Reset thread local flags and variables for the next allocation.
1949 tls->flags &= ~VLD_TLS_CRTALLOC;
1954 // _mfc80d_vector_new - Calls to the MFC vector new operator from mfc80d.dll are
1955 // patched through to this function. This function is just a wrapper around
1956 // the real MFC vector new operator that sets appropriate flags to be
1957 // consulted when the memory is actually allocated by RtlAllocateHeap.
1959 // - size (IN): The size, in bytes, of the memory block to be allocated.
1963 // Returns the value returned by the MFC vector new operator.
1965 void* VisualLeakDetector::_mfc80d_vector_new (unsigned int size)
1970 tls_t *tls = vld.gettls();
1972 // The MFC new operators are CRT-based and allocate from the CRT heap.
1973 tls->flags |= VLD_TLS_CRTALLOC;
1975 if (tls->addrfp == 0x0) {
1976 // This is the first call to enter VLD for the current allocation.
1977 // Record the current frame pointer.
1982 if (pmfc80d_vector_new == NULL) {
1983 // This is the first call to this function. Link to the real MFC 8.0 new
1985 mfc80d = GetModuleHandle(L"mfc80d.dll");
1986 pmfc80d_vector_new = (new_t)GetProcAddress(mfc80d, (LPCSTR)267);
1989 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1990 block = pmfc80d_vector_new(size);
1992 // Reset thread local flags and variables for the next allocation.
1994 tls->flags &= ~VLD_TLS_CRTALLOC;
1999 // _RtlAllocateHeap - Calls to RtlAllocateHeap are patched through to this
2000 // function. This function invokes the real RtlAllocateHeap and then calls
2001 // VLD's allocation tracking function. Pretty much all memory allocations
2002 // will eventually result in a call to RtlAllocateHeap, so this is where we
2003 // finally map the allocated block.
2005 // - heap (IN): Handle to the heap from which to allocate memory.
2007 // - flags (IN): Heap allocation control flags.
2009 // - size (IN): Size, in bytes, of the block to allocate.
2013 // Returns the return value from RtlAllocateHeap.
2015 LPVOID VisualLeakDetector::_RtlAllocateHeap (HANDLE heap, DWORD flags, SIZE_T size)
2018 BOOL excluded = FALSE;
2021 moduleinfo_t moduleinfo;
2022 ModuleSet::Iterator moduleit;
2023 SIZE_T returnaddress;
2024 tls_t *tls = vld.gettls();
2026 // Allocate the block.
2027 block = RtlAllocateHeap(heap, flags, size);
2028 if ((block != NULL) && vld.enabled()) {
2029 if (tls->addrfp == 0x0) {
2030 // This is the first call to enter VLD for the current allocation.
2031 // Record the current frame pointer.
2037 crtalloc = (tls->flags & VLD_TLS_CRTALLOC) ? TRUE : FALSE;
2039 // Reset thread local flags and variables, in case any libraries called
2040 // into while mapping the block allocate some memory.
2042 tls->flags &=~VLD_TLS_CRTALLOC;
2044 // Find the information for the module that initiated this allocation.
2045 returnaddress = *((SIZE_T*)fp + 1);
2046 moduleinfo.addrhigh = returnaddress;
2047 moduleinfo.addrlow = returnaddress;
2048 EnterCriticalSection(&vld.m_moduleslock);
2049 moduleit = vld.m_loadedmodules->find(moduleinfo);
2050 if (moduleit != vld.m_loadedmodules->end()) {
2051 excluded = (*moduleit).flags & VLD_MODULE_EXCLUDED ? TRUE : FALSE;
2053 LeaveCriticalSection(&vld.m_moduleslock);
2055 // The module that initiated this allocation is included in leak
2056 // detection. Map this block to the specified heap.
2057 vld.mapblock(heap, block, size, fp, crtalloc);
2061 // Reset thread local flags and variables for the next allocation.
2063 tls->flags &= ~VLD_TLS_CRTALLOC;
2068 // _RtlFreeHeap - Calls to RtlFreeHeap are patched through to this function.
2069 // This function calls VLD's free tracking function and then invokes the real
2070 // RtlFreeHeap. Pretty much all memory frees will eventually result in a call
2071 // to RtlFreeHeap, so this is where we finally unmap the freed block.
2073 // - heap (IN): Handle to the heap to which the block being freed belongs.
2075 // - flags (IN): Heap control flags.
2077 // - mem (IN): Pointer to the memory block being freed.
2081 // Returns the value returned by RtlFreeHeap.
2083 BOOL VisualLeakDetector::_RtlFreeHeap (HANDLE heap, DWORD flags, LPVOID mem)
2087 // Unmap the block from the specified heap.
2088 vld.unmapblock(heap, mem);
2090 status = RtlFreeHeap(heap, flags, mem);
2095 // _RtlReAllocateHeap - Calls to RtlReAllocateHeap are patched through to this
2096 // function. This function invokes the real RtlReAllocateHeap and then calls
2097 // VLD's reallocation tracking function. All arguments passed to this function
2098 // are passed on to the real RtlReAllocateHeap without modification. Pretty
2099 // much all memory re-allocations will eventually result in a call to
2100 // RtlReAllocateHeap, so this is where we finally remap the reallocated block.
2102 // - heap (IN): Handle to the heap to reallocate memory from.
2104 // - flags (IN): Heap control flags.
2106 // - mem (IN): Pointer to the currently allocated block which is to be
2109 // - size (IN): Size, in bytes, of the block to reallocate.
2113 // Returns the value returned by RtlReAllocateHeap.
2115 LPVOID VisualLeakDetector::_RtlReAllocateHeap (HANDLE heap, DWORD flags, LPVOID mem, SIZE_T size)
2118 BOOL excluded = FALSE;
2120 moduleinfo_t moduleinfo;
2121 ModuleSet::Iterator moduleit;
2123 SIZE_T returnaddress;
2124 tls_t *tls = vld.gettls();
2126 // Reallocate the block.
2127 newmem = RtlReAllocateHeap(heap, flags, mem, size);
2129 if (newmem != NULL) {
2130 if (tls->addrfp == 0x0) {
2131 // This is the first call to enter VLD for the current allocation.
2132 // Record the current frame pointer.
2138 crtalloc = (tls->flags & VLD_TLS_CRTALLOC) ? TRUE : FALSE;
2140 // Reset thread local flags and variables, in case any libraries called
2141 // into while remapping the block allocate some memory.
2143 tls->flags &= ~VLD_TLS_CRTALLOC;
2145 // Find the information for the module that initiated this reallocation.
2146 returnaddress = *((SIZE_T*)fp + 1);
2147 moduleinfo.addrhigh = returnaddress;
2148 moduleinfo.addrlow = returnaddress;
2149 EnterCriticalSection(&vld.m_moduleslock);
2150 moduleit = vld.m_loadedmodules->find(moduleinfo);
2151 if (moduleit != vld.m_loadedmodules->end()) {
2152 excluded = (*moduleit).flags & VLD_MODULE_EXCLUDED ? TRUE : FALSE;
2154 LeaveCriticalSection(&vld.m_moduleslock);
2156 // The module that initiated this allocation is included in leak
2157 // detection. Remap the block.
2158 vld.remapblock(heap, mem, newmem, size, fp, crtalloc);
2162 // Reset thread local flags and variables for the next allocation.
2164 tls->flags &= ~VLD_TLS_CRTALLOC;
2169 // AddRef - Calls to IMalloc::AddRef end up here. This function is just a
2170 // wrapper around the real IMalloc::AddRef implementation.
2174 // Returns the value returned by the system implementation of
2177 ULONG VisualLeakDetector::AddRef ()
2179 assert(m_imalloc != NULL);
2180 return m_imalloc->AddRef();
2183 // Alloc - Calls to IMalloc::Alloc end up here. This function is just a wrapper
2184 // around the real IMalloc::Alloc implementation that sets appropriate flags
2185 // to be consulted when the memory is actually allocated by RtlAllocateHeap.
2187 // - size (IN): The size of the memory block to allocate.
2191 // Returns the value returned by the system's IMalloc::Alloc implementation.
2193 LPVOID VisualLeakDetector::Alloc (ULONG size)
2197 tls_t *tls = vld.gettls();
2199 if (tls->addrfp == 0x0) {
2200 // This is the first call to enter VLD for the current allocation.
2201 // Record the current frame pointer.
2206 // Do the allocation. The block will be mapped by _RtlAllocateHeap.
2207 assert(m_imalloc != NULL);
2208 block = m_imalloc->Alloc(size);
2210 // Reset thread local flags and variables for the next allocation.
2212 tls->flags &= ~VLD_TLS_CRTALLOC;
2217 // addloadedmodule - Callback function for EnumerateLoadedModules64. This
2218 // function records information about every module loaded in the process,
2219 // each time adding the module's information to the provided ModuleSet (the
2220 // "context" parameter).
2222 // When EnumerateLoadedModules64 has finished calling this function for each
2223 // loaded module, then the resulting ModuleSet can be used at any time to get
2224 // information about any modules loaded into the process.
2226 // - modulepath (IN): The fully qualified path from where the module was
2229 // - modulebase (IN): The base address at which the module has been loaded.
2231 // - modulesize (IN): The size, in bytes, of the loaded module.
2233 // - context (IN): Pointer to the ModuleSet to which information about each
2234 // module is to be added.
2238 // Always returns TRUE, which tells EnumerateLoadedModules64 to continue
2241 BOOL VisualLeakDetector::addloadedmodule (PCWSTR modulepath, DWORD64 modulebase, ULONG modulesize, PVOID context)
2244 patchentry_t *entry;
2245 CHAR extension [_MAX_EXT];
2246 CHAR filename [_MAX_FNAME];
2248 moduleinfo_t moduleinfo;
2251 ModuleSet* newmodules = (ModuleSet*)context;
2253 UINT tablesize = sizeof(m_patchtable) / sizeof(patchentry_t);
2255 // Convert the module path to ASCII.
2256 size = wcslen(modulepath) + 1;
2257 modulepatha = new CHAR [size];
2258 wcstombs_s(&count, modulepatha, size, modulepath, _TRUNCATE);
2260 // Extract just the filename and extension from the module path.
2261 _splitpath_s(modulepatha, NULL, 0, NULL, 0, filename, _MAX_FNAME, extension, _MAX_EXT);
2262 size = strlen(filename) + strlen(extension) + 1;
2263 modulenamea = new CHAR [size];
2264 strncpy_s(modulenamea, size, filename, _TRUNCATE);
2265 strncat_s(modulenamea, size, extension, _TRUNCATE);
2266 _strlwr_s(modulenamea, size);
2268 if (_stricmp(modulenamea, "vld.dll") == 0) {
2269 // Record Visual Leak Detector's own base address.
2270 vld.m_vldbase = (HMODULE)modulebase;
2273 // See if this is a module listed in the patch table. If it is, update
2274 // the corresponding patch table entries' module base address.
2275 for (index = 0; index < tablesize; index++) {
2276 entry = &m_patchtable[index];
2277 if (_stricmp(entry->exportmodulename, modulenamea) == 0) {
2278 entry->modulebase = (SIZE_T)modulebase;
2283 // Record the module's information and store it in the set.
2284 moduleinfo.addrlow = (SIZE_T)modulebase;
2285 moduleinfo.addrhigh = (SIZE_T)(modulebase + modulesize) - 1;
2286 moduleinfo.flags = 0x0;
2287 moduleinfo.name = modulenamea;
2288 moduleinfo.path = modulepatha;
2289 newmodules->insert(moduleinfo);
2294 // attachtoloadedmodules - Attaches VLD to all modules contained in the provided
2295 // ModuleSet. Not all modules are in the ModuleSet will actually be included
2296 // in leak detection. Only modules that import the global VisualLeakDetector
2297 // class object, or those that are otherwise explicitly included in leak
2298 // detection, will be checked for memory leaks.
2300 // When VLD attaches to a module, it means that any of the imports listed in
2301 // the import patch table which are imported by the module, will be redirected
2302 // to VLD's designated replacements.
2304 // - newmodules (IN): Pointer to a ModuleSet containing information about any
2305 // loaded modules that need to be attached.
2311 VOID VisualLeakDetector::attachtoloadedmodules (ModuleSet *newmodules)
2316 IMAGEHLP_MODULE64 moduleimageinfo;
2318 #define MAXMODULENAME (_MAX_FNAME + _MAX_EXT)
2319 WCHAR modulenamew [MAXMODULENAME];
2322 ModuleSet::Iterator newit;
2323 ModuleSet::Iterator oldit;
2324 ModuleSet *oldmodules;
2326 UINT tablesize = sizeof(m_patchtable) / sizeof(patchentry_t);
2327 ModuleSet::Muterator updateit;
2329 // Iterate through the supplied set, until all modules have been attached.
2330 for (newit = newmodules->begin(); newit != newmodules->end(); ++newit) {
2331 modulebase = (DWORD64)(*newit).addrlow;
2333 modulename = (*newit).name;
2334 modulepath = (*newit).path;
2335 modulesize = (DWORD)((*newit).addrhigh - (*newit).addrlow) + 1;
2338 EnterCriticalSection(&m_moduleslock);
2339 oldmodules = m_loadedmodules;
2340 if (oldmodules != NULL) {
2341 // This is not the first time we have been called to attach to the
2342 // currently loaded modules.
2343 oldit = oldmodules->find(*newit);
2344 if (oldit != oldmodules->end()) {
2345 // We've seen this "new" module loaded in the process before.
2346 moduleflags = (*oldit).flags;
2347 LeaveCriticalSection(&m_moduleslock);
2348 if (moduleispatched((HMODULE)modulebase, m_patchtable, tablesize)) {
2349 // This module is already attached. Just update the module's
2350 // flags, nothing more.
2352 (*updateit).flags = moduleflags;
2356 // This module may have been attached before and has been
2357 // detached. We'll need to try reattaching to it in case it
2358 // was unloaded and then subsequently reloaded.
2363 LeaveCriticalSection(&m_moduleslock);
2367 LeaveCriticalSection(&m_moduleslock);
2370 EnterCriticalSection(&symbollock);
2371 if ((refresh == TRUE) && (moduleflags & VLD_MODULE_SYMBOLSLOADED)) {
2372 // Discard the previously loaded symbols, so we can refresh them.
2373 if (SymUnloadModule64(currentprocess, modulebase) == FALSE) {
2374 report(L"WARNING: Visual Leak Detector: Failed to unload the symbols for %s. Function names and line"
2375 L" numbers shown in the memory leak report for %s may be inaccurate.", modulename, modulename);
2379 // Try to load the module's symbols. This ensures that we have loaded
2380 // the symbols for every module that has ever been loaded into the
2381 // process, guaranteeing the symbols' availability when generating the
2383 moduleimageinfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
2384 if ((SymGetModuleInfoW64(currentprocess, (DWORD64)modulebase, &moduleimageinfo) == TRUE) ||
2385 ((SymLoadModule64(currentprocess, NULL, modulepath, NULL, modulebase, modulesize) == modulebase) &&
2386 (SymGetModuleInfoW64(currentprocess, modulebase, &moduleimageinfo) == TRUE))) {
2387 moduleflags |= VLD_MODULE_SYMBOLSLOADED;
2389 LeaveCriticalSection(&symbollock);
2391 if (_stricmp("vld.dll", modulename) == 0) {
2392 // What happens when a module goes through it's own portal? Bad things.
2393 // Like infinite recursion. And ugly bald men wearing dresses. VLD
2394 // should not, therefore, attach to itself.
2398 mbstowcs_s(&count, modulenamew, MAXMODULENAME, modulename, _TRUNCATE);
2399 if ((findimport((HMODULE)modulebase, m_vldbase, "vld.dll", "?vld@@3VVisualLeakDetector@@A") == FALSE) &&
2400 (wcsstr(vld.m_forcedmodulelist, modulenamew) == NULL)) {
2401 // This module does not import VLD. This means that none of the module's
2402 // sources #included vld.h. Exclude this module from leak detection.
2403 moduleflags |= VLD_MODULE_EXCLUDED;
2405 else if (!(moduleflags & VLD_MODULE_SYMBOLSLOADED) || (moduleimageinfo.SymType == SymExport)) {
2406 // This module is going to be included in leak detection, but complete
2407 // symbols for this module couldn't be loaded. This means that any stack
2408 // traces through this module may lack information, like line numbers
2409 // and function names.
2410 report(L"WARNING: Visual Leak Detector: A module, %s, included in memory leak detection\n"
2411 L" does not have any debugging symbols available, or they could not be located.\n"
2412 L" Function names and/or line numbers for this module may not be available.\n", modulename);
2415 // Update the module's flags in the "new modules" set.
2417 (*updateit).flags = moduleflags;
2419 // Attach to the module.
2420 patchmodule((HMODULE)modulebase, m_patchtable, tablesize);
2424 // buildsymbolsearchpath - Builds the symbol search path for the symbol handler.
2425 // This helps the symbol handler find the symbols for the application being
2430 // Returns a string containing the search path. The caller is responsible for
2431 // freeing the string.
2433 LPWSTR VisualLeakDetector::buildsymbolsearchpath ()
2435 WCHAR directory [_MAX_DIR];
2436 WCHAR drive [_MAX_DRIVE];
2442 LPWSTR path = new WCHAR [MAX_PATH];
2444 WCHAR system [MAX_PATH];
2445 WCHAR windows [MAX_PATH];
2447 // Oddly, the symbol handler ignores the link to the PDB embedded in the
2448 // executable image. So, we'll manually add the location of the executable
2449 // to the search path since that is often where the PDB will be located.
2451 module = GetModuleHandle(NULL);
2452 GetModuleFileName(module, path, MAX_PATH);
2453 _wsplitpath_s(path, drive, _MAX_DRIVE, directory, _MAX_DIR, NULL, 0, NULL, 0);
2454 wcsncpy_s(path, MAX_PATH, drive, _TRUNCATE);
2455 strapp(&path, directory);
2457 // When the symbol handler is given a custom symbol search path, it will no
2458 // longer search the default directories (working directory, system root,
2459 // etc). But we'd like it to still search those directories, so we'll add
2460 // them to our custom search path.
2462 // Append the working directory.
2463 strapp(&path, L";.\\");
2465 // Append the Windows directory.
2466 if (GetWindowsDirectory(windows, MAX_PATH) != 0) {
2467 strapp(&path, L";");
2468 strapp(&path, windows);
2471 // Append the system directory.
2472 if (GetSystemDirectory(system, MAX_PATH) != 0) {
2473 strapp(&path, L";");
2474 strapp(&path, system);
2477 // Append %_NT_SYMBOL_PATH%.
2478 envlen = GetEnvironmentVariable(L"_NT_SYMBOL_PATH", NULL, 0);
2480 env = new WCHAR [envlen];
2481 if (GetEnvironmentVariable(L"_NT_SYMBOL_PATH", env, envlen) != 0) {
2482 strapp(&path, L";");
2488 // Append %_NT_ALT_SYMBOL_PATH%.
2489 envlen = GetEnvironmentVariable(L"_NT_ALT_SYMBOL_PATH", NULL, 0);
2491 env = new WCHAR [envlen];
2492 if (GetEnvironmentVariable(L"_NT_ALT_SYMBOL_PATH", env, envlen) != 0) {
2493 strapp(&path, L";");
2499 // Remove any quotes from the path. The symbol handler doesn't like them.
2501 length = wcslen(path);
2502 while (pos < length) {
2503 if (path[pos] == L'\"') {
2504 for (index = pos; index < length; index++) {
2505 path[index] = path[index + 1];
2514 // configure - Configures VLD using values read from the vld.ini file.
2520 VOID VisualLeakDetector::configure ()
2523 WCHAR buffer [BSIZE];
2524 WCHAR filename [MAX_PATH];
2525 WCHAR inipath [MAX_PATH];
2526 BOOL keyopen = FALSE;
2533 if (_wstat(L".\\vld.ini", &s) == 0) {
2534 // Found a copy of vld.ini in the working directory. Use it.
2535 wcsncpy_s(inipath, MAX_PATH, L".\\vld.ini", _TRUNCATE);
2538 // Get the location of the vld.ini file from the registry.
2539 regstatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, VLDREGKEYPRODUCT, 0, KEY_QUERY_VALUE, &productkey);
2540 if (regstatus == ERROR_SUCCESS) {
2542 regstatus = RegQueryValueEx(productkey, L"IniFile", NULL, &valuetype, (LPBYTE)&inipath, &length);
2545 RegCloseKey(productkey);
2547 if ((regstatus != ERROR_SUCCESS) || (_wstat(inipath, &s) != 0)) {
2548 // The location of vld.ini could not be read from the registry. As a
2549 // last resort, look in the Windows directory.
2550 wcsncpy_s(inipath, MAX_PATH, L"vld.ini", _TRUNCATE);
2554 // Read the boolean options.
2555 GetPrivateProfileString(L"Options", L"VLD", L"on", buffer, BSIZE, inipath);
2556 if (strtobool(buffer) == FALSE) {
2557 m_options |= VLD_OPT_VLDOFF;
2561 GetPrivateProfileString(L"Options", L"AggregateDuplicates", L"", buffer, BSIZE, inipath);
2562 if (strtobool(buffer) == TRUE) {
2563 m_options |= VLD_OPT_AGGREGATE_DUPLICATES;
2566 GetPrivateProfileString(L"Options", L"SelfTest", L"", buffer, BSIZE, inipath);
2567 if (strtobool(buffer) == TRUE) {
2568 m_options |= VLD_OPT_SELF_TEST;
2571 GetPrivateProfileString(L"Options", L"SlowDebuggerDump", L"", buffer, BSIZE, inipath);
2572 if (strtobool(buffer) == TRUE) {
2573 m_options |= VLD_OPT_SLOW_DEBUGGER_DUMP;
2576 GetPrivateProfileString(L"Options", L"StartDisabled", L"", buffer, BSIZE, inipath);
2577 if (strtobool(buffer) == TRUE) {
2578 m_options |= VLD_OPT_START_DISABLED;
2581 GetPrivateProfileString(L"Options", L"TraceInternalFrames", L"", buffer, BSIZE, inipath);
2582 if (strtobool(buffer) == TRUE) {
2583 m_options |= VLD_OPT_TRACE_INTERNAL_FRAMES;
2586 // Read the integer configuration options.
2587 m_maxdatadump = GetPrivateProfileInt(L"Options", L"MaxDataDump", VLD_DEFAULT_MAX_DATA_DUMP, inipath);
2588 m_maxtraceframes = GetPrivateProfileInt(L"Options", L"MaxTraceFrames", VLD_DEFAULT_MAX_TRACE_FRAMES, inipath);
2589 if (m_maxtraceframes < 1) {
2590 m_maxtraceframes = VLD_DEFAULT_MAX_TRACE_FRAMES;
2593 // Read the force-include module list.
2594 GetPrivateProfileString(L"Options", L"ForceIncludeModules", L"", m_forcedmodulelist, MAXMODULELISTLENGTH, inipath);
2595 _wcslwr_s(m_forcedmodulelist, MAXMODULELISTLENGTH);
2597 // Read the report destination (debugger, file, or both).
2598 GetPrivateProfileString(L"Options", L"ReportFile", L"", filename, MAX_PATH, inipath);
2599 if (wcslen(filename) == 0) {
2600 wcsncpy_s(filename, MAX_PATH, VLD_DEFAULT_REPORT_FILE_NAME, _TRUNCATE);
2602 _wfullpath(m_reportfilepath, filename, MAX_PATH);
2603 GetPrivateProfileString(L"Options", L"ReportTo", L"", buffer, BSIZE, inipath);
2604 if (_wcsicmp(buffer, L"both") == 0) {
2605 m_options |= (VLD_OPT_REPORT_TO_DEBUGGER | VLD_OPT_REPORT_TO_FILE);
2607 else if (_wcsicmp(buffer, L"file") == 0) {
2608 m_options |= VLD_OPT_REPORT_TO_FILE;
2611 m_options |= VLD_OPT_REPORT_TO_DEBUGGER;
2614 // Read the report file encoding (ascii or unicode).
2615 GetPrivateProfileString(L"Options", L"ReportEncoding", L"", buffer, BSIZE, inipath);
2616 if (_wcsicmp(buffer, L"unicode") == 0) {
2617 m_options |= VLD_OPT_UNICODE_REPORT;
2619 if ((m_options & VLD_OPT_UNICODE_REPORT) && !(m_options & VLD_OPT_REPORT_TO_FILE)) {
2620 // If Unicode report encoding is enabled, then the report needs to be
2621 // sent to a file because the debugger will not display Unicode
2622 // characters, it will display question marks in their place instead.
2623 m_options |= VLD_OPT_REPORT_TO_FILE;
2624 m_status |= VLD_STATUS_FORCE_REPORT_TO_FILE;
2627 // Read the stack walking method.
2628 GetPrivateProfileString(L"Options", L"StackWalkMethod", L"", buffer, BSIZE, inipath);
2629 if (_wcsicmp(buffer, L"safe") == 0) {
2630 m_options |= VLD_OPT_SAFE_STACK_WALK;
2634 // detachfrommodule - Callback function for EnumerateLoadedModules64 that
2635 // detaches Visual Leak Detector from the specified module. If the specified
2636 // module has not previously been attached to, then calling this function will
2637 // not actually result in any changes.
2639 // - modulepath (IN): String containing the name, which may inlcude a path, of
2640 // the module to detach from (ignored).
2642 // - modulebase (IN): Base address of the module.
2644 // - modulesize (IN): Total size of the module (ignored).
2646 // - context (IN): User-supplied context (ignored).
2650 // Always returns TRUE.
2652 BOOL VisualLeakDetector::detachfrommodule (PCWSTR /*modulepath*/, DWORD64 modulebase, ULONG /*modulesize*/,
2655 UINT tablesize = sizeof(m_patchtable) / sizeof(patchentry_t);
2657 restoremodule((HMODULE)modulebase, m_patchtable, tablesize);
2662 // DidAlloc - Calls to IMalloc::DidAlloc will end up here. This function is just
2663 // a wrapper around the system implementation of IMalloc::DidAlloc.
2665 // - mem (IN): Pointer to a memory block to inquire about.
2669 // Returns the value returned by the system implementation of
2670 // IMalloc::DidAlloc.
2672 INT VisualLeakDetector::DidAlloc (LPVOID mem)
2674 assert(m_imalloc != NULL);
2675 return m_imalloc->DidAlloc(mem);
2678 // enabled - Determines if memory leak detection is enabled for the current
2683 // Returns true if Visual Leak Detector is enabled for the current thread.
2684 // Otherwise, returns false.
2686 BOOL VisualLeakDetector::enabled ()
2688 tls_t *tls = vld.gettls();
2690 if (!(m_status & VLD_STATUS_INSTALLED)) {
2691 // Memory leak detection is not yet enabled because VLD is still
2696 if (!(tls->flags & VLD_TLS_DISABLED) && !(tls->flags & VLD_TLS_ENABLED)) {
2697 // The enabled/disabled state for the current thread has not been
2698 // initialized yet. Use the default state.
2699 if (m_options & VLD_OPT_START_DISABLED) {
2700 tls->flags |= VLD_TLS_DISABLED;
2703 tls->flags |= VLD_TLS_ENABLED;
2707 return ((tls->flags & VLD_TLS_ENABLED) != 0);
2710 // eraseduplicates - Erases, from the block maps, blocks that appear to be
2711 // duplicate leaks of an already identified leak.
2713 // - element (IN): BlockMap Iterator referencing the block of which to search
2718 // Returns the number of duplicate blocks erased from the block map.
2720 SIZE_T VisualLeakDetector::eraseduplicates (const BlockMap::Iterator &element)
2722 BlockMap::Iterator blockit;
2724 blockinfo_t *elementinfo;
2726 HeapMap::Iterator heapit;
2728 BlockMap::Iterator previt;
2730 elementinfo = (*element).second;
2732 // Iteratate through all block maps, looking for blocks with the same size
2733 // and callstack as the specified element.
2734 for (heapit = m_heapmap->begin(); heapit != m_heapmap->end(); ++heapit) {
2735 blockmap = &(*heapit).second->blockmap;
2736 for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
2737 if (blockit == element) {
2738 // Don't delete the element of which we are searching for
2742 info = (*blockit).second;
2743 if ((info->size == elementinfo->size) && (*(info->callstack) == *(elementinfo->callstack))) {
2744 // Found a duplicate. Erase it.
2745 delete info->callstack;
2747 previt = blockit - 1;
2748 blockmap->erase(blockit);
2758 // Free - Calls to IMalloc::Free will end up here. This function is just a
2759 // wrapper around the real IMalloc::Free implementation.
2761 // - mem (IN): Pointer to the memory block to be freed.
2767 VOID VisualLeakDetector::Free (LPVOID mem)
2769 assert(m_imalloc != NULL);
2770 m_imalloc->Free(mem);
2773 // GetSize - Calls to IMalloc::GetSize will end up here. This function is just a
2774 // wrapper around the real IMalloc::GetSize implementation.
2776 // - mem (IN): Pointer to the memory block to inquire about.
2780 // Returns the value returned by the system implementation of
2781 // IMalloc::GetSize.
2783 ULONG VisualLeakDetector::GetSize (LPVOID mem)
2785 assert(m_imalloc != NULL);
2786 return m_imalloc->GetSize(mem);
2789 // gettls - Obtains the thread local strorage structure for the calling thread.
2793 // Returns a pointer to the thread local storage structure. (This function
2794 // always succeeds).
2796 tls_t* VisualLeakDetector::gettls ()
2800 // Get the pointer to this thread's thread local storage structure.
2801 tls = (tls_t*)TlsGetValue(m_tlsindex);
2802 assert(GetLastError() == ERROR_SUCCESS);
2805 // This thread's thread local storage structure has not been allocated.
2807 TlsSetValue(m_tlsindex, tls);
2810 tls->threadid = GetCurrentThreadId();
2812 // Add this thread's TLS to the TlsSet.
2813 EnterCriticalSection(&m_tlslock);
2814 m_tlsset->insert(tls);
2815 LeaveCriticalSection(&m_tlslock);
2821 // HeapMinimize - Calls to IMalloc::HeapMinimize will end up here. This function
2822 // is just a wrapper around the real IMalloc::HeapMinimize implementation.
2828 VOID VisualLeakDetector::HeapMinimize ()
2830 assert(m_imalloc != NULL);
2831 m_imalloc->HeapMinimize();
2834 // mapblock - Tracks memory allocations. Information about allocated blocks is
2835 // collected and then the block is mapped to this information.
2837 // - heap (IN): Handle to the heap from which the block has been allocated.
2839 // - mem (IN): Pointer to the memory block being allocated.
2841 // - size (IN): Size, in bytes, of the memory block being allocated.
2843 // - framepointer (IN): Framepointer at the time this allocation first entered
2844 // VLD's code. This is used from determining the starting point for the
2847 // - crtalloc (IN): Should be set to TRUE if this allocation is a CRT memory
2848 // block. Otherwise should be FALSE.
2854 VOID VisualLeakDetector::mapblock (HANDLE heap, LPCVOID mem, SIZE_T size, SIZE_T framepointer, BOOL crtalloc)
2856 blockinfo_t *blockinfo;
2857 BlockMap::Iterator blockit;
2859 HeapMap::Iterator heapit;
2860 static SIZE_T serialnumber = 0;
2862 // Record the block's information.
2863 blockinfo = new blockinfo_t;
2864 if (m_options & VLD_OPT_SAFE_STACK_WALK) {
2865 blockinfo->callstack = new SafeCallStack;
2868 blockinfo->callstack = new FastCallStack;
2870 if (m_options & VLD_OPT_TRACE_INTERNAL_FRAMES) {
2871 // Passing NULL for the frame pointer argument will force the stack
2872 // trace to begin at the current frame.
2873 blockinfo->callstack->getstacktrace(m_maxtraceframes, NULL);
2876 // Start the stack trace at the call that first entered VLD's code.
2877 blockinfo->callstack->getstacktrace(m_maxtraceframes, (SIZE_T*)framepointer);
2879 blockinfo->serialnumber = serialnumber++;
2880 blockinfo->size = size;
2882 // Insert the block's information into the block map.
2883 EnterCriticalSection(&m_maplock);
2884 heapit = m_heapmap->find(heap);
2885 if (heapit == m_heapmap->end()) {
2886 // We haven't mapped this heap to a block map yet. Do it now.
2888 heapit = m_heapmap->find(heap);
2889 assert(heapit != m_heapmap->end());
2891 if (crtalloc == TRUE) {
2892 // The heap that this block was allocated from is a CRT heap.
2893 (*heapit).second->flags |= VLD_HEAP_CRT;
2895 blockmap = &(*heapit).second->blockmap;
2896 blockit = blockmap->insert(mem, blockinfo);
2897 if (blockit == blockmap->end()) {
2898 // A block with this address has already been allocated. The
2899 // previously allocated block must have been freed (probably by some
2900 // mechanism unknown to VLD), or the heap wouldn't have allocated it
2901 // again. Replace the previously allocated info with the new info.
2902 blockit = blockmap->find(mem);
2903 delete (*blockit).second->callstack;
2904 delete (*blockit).second;
2905 blockmap->erase(blockit);
2906 blockmap->insert(mem, blockinfo);
2908 LeaveCriticalSection(&m_maplock);
2911 // mapheap - Tracks heap creation. Creates a block map for tracking individual
2912 // allocations from the newly created heap and then maps the heap to this
2915 // - heap (IN): Handle to the newly created heap.
2921 VOID VisualLeakDetector::mapheap (HANDLE heap)
2923 heapinfo_t *heapinfo;
2924 HeapMap::Iterator heapit;
2926 // Create a new block map for this heap and insert it into the heap map.
2927 heapinfo = new heapinfo_t;
2928 heapinfo->blockmap.reserve(BLOCKMAPRESERVE);
2929 heapinfo->flags = 0x0;
2930 EnterCriticalSection(&m_maplock);
2931 heapit = m_heapmap->insert(heap, heapinfo);
2932 if (heapit == m_heapmap->end()) {
2933 // Somehow this heap has been created twice without being destroyed,
2934 // or at least it was destroyed without VLD's knowledge. Unmap the heap
2935 // from the existing heapinfo, and remap it to the new one.
2936 report(L"WARNING: Visual Leak Detector detected a duplicate heap (" ADDRESSFORMAT L").\n", heap);
2937 heapit = m_heapmap->find(heap);
2938 unmapheap((*heapit).first);
2939 m_heapmap->insert(heap, heapinfo);
2941 LeaveCriticalSection(&m_maplock);
2944 // QueryInterface - Calls to IMalloc::QueryInterface will end up here. This
2945 // function is just a wrapper around the real IMalloc::QueryInterface
2948 // - iid (IN): COM interface ID to query about.
2950 // - object (IN): Address of a pointer to receive the requested interface
2955 // Returns the value returned by the system implementation of
2956 // IMalloc::QueryInterface.
2958 HRESULT VisualLeakDetector::QueryInterface (REFIID iid, LPVOID *object)
2960 assert(m_imalloc != NULL);
2961 return m_imalloc->QueryInterface(iid, object);
2964 // Realloc - Calls to IMalloc::Realloc will end up here. This function is just a
2965 // wrapper around the real IMalloc::Realloc implementation that sets
2966 // appropriate flags to be consulted when the memory is actually allocated by
2969 // - mem (IN): Pointer to the memory block to reallocate.
2971 // - size (IN): Size, in bytes, of the memory block to reallocate.
2975 // Returns the value returned by the system implementation of
2976 // IMalloc::Realloc.
2978 LPVOID VisualLeakDetector::Realloc (LPVOID mem, ULONG size)
2982 tls_t *tls = vld.gettls();
2984 if (tls->addrfp == 0x0) {
2985 // This is the first call to enter VLD for the current allocation.
2986 // Record the current frame pointer.
2991 // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
2992 assert(m_imalloc != NULL);
2993 block = m_imalloc->Realloc(mem, size);
2995 // Reset thread local flags and variables for the next allocation.
2997 tls->flags &= ~VLD_TLS_CRTALLOC;
3002 // Release - Calls to IMalloc::Release will end up here. This function is just
3003 // a wrapper around the real IMalloc::Release implementation.
3007 // Returns the value returned by the system implementation of
3008 // IMalloc::Release.
3010 ULONG VisualLeakDetector::Release ()
3012 assert(m_imalloc != NULL);
3013 return m_imalloc->Release();
3016 // remapblock - Tracks reallocations. Unmaps a block from its previously
3017 // collected information and remaps it to updated information.
3019 // Note: If the block itself remains at the same address, then the block's
3020 // information can simply be updated rather than having to actually erase and
3021 // reinsert the block.
3023 // - heap (IN): Handle to the heap from which the memory is being reallocated.
3025 // - mem (IN): Pointer to the memory block being reallocated.
3027 // - newmem (IN): Pointer to the memory block being returned to the caller
3028 // that requested the reallocation. This pointer may or may not be the same
3029 // as the original memory block (as pointed to by "mem").
3031 // - size (IN): Size, in bytes, of the new memory block.
3033 // - framepointer (IN): The frame pointer at which this reallocation entered
3034 // VLD's code. Used for determining the starting point of the stack trace.
3036 // - crtalloc (IN): Should be set to TRUE if this reallocation is for a CRT
3037 // memory block. Otherwise should be set to FALSE.
3043 VOID VisualLeakDetector::remapblock (HANDLE heap, LPCVOID mem, LPCVOID newmem, SIZE_T size, SIZE_T framepointer,
3046 BlockMap::Iterator blockit;
3048 HeapMap::Iterator heapit;
3051 if (newmem != mem) {
3052 // The block was not reallocated in-place. Instead the old block was
3053 // freed and a new block allocated to satisfy the new size.
3054 unmapblock(heap, mem);
3055 mapblock(heap, newmem, size, framepointer, crtalloc);
3059 // The block was reallocated in-place. Find the existing blockinfo_t
3060 // entry in the block map and update it with the new callstack and size.
3061 EnterCriticalSection(&m_maplock);
3062 heapit = m_heapmap->find(heap);
3063 if (heapit == m_heapmap->end()) {
3064 // We haven't mapped this heap to a block map yet. Obviously the
3065 // block has also not been mapped to a blockinfo_t entry yet either,
3066 // so treat this reallocation as a brand-new allocation (this will
3067 // also map the heap to a new block map).
3068 mapblock(heap, newmem, size, framepointer, crtalloc);
3069 LeaveCriticalSection(&m_maplock);
3073 // Find the block's blockinfo_t structure so that we can update it.
3074 blockmap = &(*heapit).second->blockmap;
3075 blockit = blockmap->find(mem);
3076 if (blockit == blockmap->end()) {
3077 // The block hasn't been mapped to a blockinfo_t entry yet.
3078 // Treat this reallocation as a new allocation.
3079 mapblock(heap, newmem, size, framepointer, crtalloc);
3080 LeaveCriticalSection(&m_maplock);
3084 // Found the blockinfo_t entry for this block. Update it with
3085 // a new callstack and new size.
3086 info = (*blockit).second;
3087 info->callstack->clear();
3089 // The heap that this block was allocated from is a CRT heap.
3090 (*heapit).second->flags |= VLD_HEAP_CRT;
3092 LeaveCriticalSection(&m_maplock);
3094 // Update the block's callstack and size.
3095 if (m_options & VLD_OPT_TRACE_INTERNAL_FRAMES) {
3096 // Passing NULL for the frame pointer argument will force
3097 // the stack trace to begin at the current frame.
3098 info->callstack->getstacktrace(m_maxtraceframes, NULL);
3101 // Start the stack trace at the call that first entered
3103 info->callstack->getstacktrace(m_maxtraceframes, (SIZE_T*)framepointer);
3108 // reportconfig - Generates a brief report summarizing Visual Leak Detector's
3109 // configuration, as loaded from the vld.ini file.
3115 VOID VisualLeakDetector::reportconfig ()
3117 if (m_options & VLD_OPT_AGGREGATE_DUPLICATES) {
3118 report(L" Aggregating duplicate leaks.\n");
3120 if (wcslen(m_forcedmodulelist) != 0) {
3121 report(L" Forcing inclusion of these modules in leak detection: %s\n", m_forcedmodulelist);
3123 if (m_maxdatadump != VLD_DEFAULT_MAX_DATA_DUMP) {
3124 if (m_maxdatadump == 0) {
3125 report(L" Suppressing data dumps.\n");
3128 report(L" Limiting data dumps to %lu bytes.\n", m_maxdatadump);
3131 if (m_maxtraceframes != VLD_DEFAULT_MAX_TRACE_FRAMES) {
3132 report(L" Limiting stack traces to %u frames.\n", m_maxtraceframes);
3134 if (m_options & VLD_OPT_UNICODE_REPORT) {
3135 report(L" Generating a Unicode (UTF-16) encoded report.\n");
3137 if (m_options & VLD_OPT_REPORT_TO_FILE) {
3138 if (m_options & VLD_OPT_REPORT_TO_DEBUGGER) {
3139 report(L" Outputting the report to the debugger and to %s\n", m_reportfilepath);
3142 report(L" Outputting the report to %s\n", m_reportfilepath);
3145 if (m_options & VLD_OPT_SLOW_DEBUGGER_DUMP) {
3146 report(L" Outputting the report to the debugger at a slower rate.\n");
3148 if (m_options & VLD_OPT_SAFE_STACK_WALK) {
3149 report(L" Using the \"safe\" (but slow) stack walking method.\n");
3151 if (m_options & VLD_OPT_SELF_TEST) {
3152 report(L" Perfoming a memory leak self-test.\n");
3154 if (m_options & VLD_OPT_START_DISABLED) {
3155 report(L" Starting with memory leak detection disabled.\n");
3157 if (m_options & VLD_OPT_TRACE_INTERNAL_FRAMES) {
3158 report(L" Including heap and VLD internal frames in stack traces.\n");
3162 // reportleaks - Generates a memory leak report for the specified heap.
3164 // - heap (IN): Handle to the heap for which to generate a memory leak
3171 VOID VisualLeakDetector::reportleaks (HANDLE heap)
3175 BlockMap::Iterator blockit;
3177 crtdbgblockheader_t *crtheader;
3179 heapinfo_t *heapinfo;
3180 HeapMap::Iterator heapit;
3184 // Find the heap's information (blockmap, etc).
3185 EnterCriticalSection(&m_maplock);
3186 heapit = m_heapmap->find(heap);
3187 if (heapit == m_heapmap->end()) {
3188 // Nothing is allocated from this heap. No leaks.
3189 LeaveCriticalSection(&m_maplock);
3193 heapinfo = (*heapit).second;
3194 blockmap = &heapinfo->blockmap;
3195 for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
3196 // Found a block which is still in the BlockMap. We've identified a
3197 // potential memory leak.
3198 block = (*blockit).first;
3199 info = (*blockit).second;
3202 if (heapinfo->flags & VLD_HEAP_CRT) {
3203 // This block is allocated to a CRT heap, so the block has a CRT
3204 // memory block header prepended to it.
3205 crtheader = (crtdbgblockheader_t*)block;
3206 if (CRT_USE_TYPE(crtheader->use) == CRT_USE_INTERNAL) {
3207 // This block is marked as being used internally by the CRT.
3208 // The CRT will free the block after VLD is destroyed.
3211 // The CRT header is more or less transparent to the user, so
3212 // the information about the contained block will probably be
3213 // more useful to the user. Accordingly, that's the information
3214 // we'll include in the report.
3215 address = CRTDBGBLOCKDATA(block);
3216 size = crtheader->size;
3218 // It looks like a real memory leak.
3219 if (m_leaksfound == 0) {
3220 report(L"WARNING: Visual Leak Detector detected memory leaks!\n");
3223 report(L"---------- Block %ld at " ADDRESSFORMAT L": %u bytes ----------\n", info->serialnumber, address, size);
3224 if (m_options & VLD_OPT_AGGREGATE_DUPLICATES) {
3225 // Aggregate all other leaks which are duplicates of this one
3226 // under this same heading, to cut down on clutter.
3227 duplicates = eraseduplicates(blockit);
3229 report(L"A total of %lu leaks match this size and call stack. Showing only the first one.\n",
3231 m_leaksfound += duplicates;
3234 // Dump the call stack.
3235 report(L" Call Stack:\n");
3236 info->callstack->dump(m_options & VLD_OPT_TRACE_INTERNAL_FRAMES);
3237 // Dump the data in the user data section of the memory block.
3238 if (m_maxdatadump != 0) {
3239 report(L" Data:\n");
3240 if (m_options & VLD_OPT_UNICODE_REPORT) {
3241 dumpmemoryw(address, (m_maxdatadump < size) ? m_maxdatadump : size);
3244 dumpmemorya(address, (m_maxdatadump < size) ? m_maxdatadump : size);
3250 LeaveCriticalSection(&m_maplock);
3253 // unmapblock - Tracks memory blocks that are freed. Unmaps the specified block
3254 // from the block's information, relinquishing internally allocated resources.
3256 // - heap (IN): Handle to the heap to which this block is being freed.
3258 // - mem (IN): Pointer to the memory block being freed.
3264 VOID VisualLeakDetector::unmapblock (HANDLE heap, LPCVOID mem)
3266 BlockMap::Iterator blockit;
3268 HeapMap::Iterator heapit;
3271 // Find this heap's block map.
3272 EnterCriticalSection(&m_maplock);
3273 heapit = m_heapmap->find(heap);
3274 if (heapit == m_heapmap->end()) {
3275 // We don't have a block map for this heap. We must not have monitored
3276 // this allocation (probably happened before VLD was initialized).
3277 LeaveCriticalSection(&m_maplock);
3281 // Find this block in the block map.
3282 blockmap = &(*heapit).second->blockmap;
3283 blockit = blockmap->find(mem);
3284 if (blockit == blockmap->end()) {
3285 // This block is not in the block map. We must not have monitored this
3286 // allocation (probably happened before VLD was initialized).
3287 LeaveCriticalSection(&m_maplock);
3291 // Free the blockinfo_t structure and erase it from the block map.
3292 info = (*blockit).second;
3293 delete info->callstack;
3295 blockmap->erase(blockit);
3296 LeaveCriticalSection(&m_maplock);
3299 // unmapheap - Tracks heap destruction. Unmaps the specified heap from its block
3300 // map. The block map is cleared and deleted, relinquishing internally
3301 // allocated resources.
3303 // - heap (IN): Handle to the heap which is being destroyed.
3309 VOID VisualLeakDetector::unmapheap (HANDLE heap)
3311 BlockMap::Iterator blockit;
3313 heapinfo_t *heapinfo;
3314 HeapMap::Iterator heapit;
3316 // Find this heap's block map.
3317 EnterCriticalSection(&m_maplock);
3318 heapit = m_heapmap->find(heap);
3319 if (heapit == m_heapmap->end()) {
3320 // This heap hasn't been mapped. We must not have monitored this heap's
3321 // creation (probably happened before VLD was initialized).
3322 LeaveCriticalSection(&m_maplock);
3326 // Free all of the blockinfo_t structures stored in the block map.
3327 heapinfo = (*heapit).second;
3328 blockmap = &heapinfo->blockmap;
3329 for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
3330 delete (*blockit).second->callstack;
3331 delete (*blockit).second;
3335 // Remove this heap's block map from the heap map.
3336 m_heapmap->erase(heapit);
3337 LeaveCriticalSection(&m_maplock);