From fd4ee387c9cf7e81a6a6f2aaee00e6d8885eb9a0 Mon Sep 17 00:00:00 2001 From: Arkady Shapkin Date: Sun, 6 Apr 2014 21:29:16 +0400 Subject: [PATCH] VLD will display last internal frame --- callstack.cpp | 24 +++- tests/basics/Allocs.cpp | 241 +++++++++++++++++----------------- tests/basics/basics.cpp | 6 +- tests/basics/stdafx.h | 1 - tests/dynamic_dll/dllmain.cpp | 21 ++- vld_hooks.cpp | 28 ++-- 6 files changed, 168 insertions(+), 153 deletions(-) diff --git a/callstack.cpp b/callstack.cpp index 63b17a84..57439dd5 100644 --- a/callstack.cpp +++ b/callstack.cpp @@ -221,6 +221,11 @@ void CallStack::dump(BOOL showInternalFrames, UINT start_frame) const const size_t max_size = MAXREPORTLENGTH + 1; + // Use static here to increase performance, and avoid heap allocs. Hopefully this won't + // prove to be an issue in thread safety. If it does, it will have to be simply non-static. + static WCHAR stack_line[MAXREPORTLENGTH + 1] = L""; + bool isPrevFrameInternal = false; + // Iterate through each frame in the call stack. for (UINT32 frame = start_frame; frame < m_size; frame++) { @@ -232,13 +237,15 @@ void CallStack::dump(BOOL showInternalFrames, UINT start_frame) const DWORD displacement = 0; DbgTrace(L"dbghelp32.dll %i: SymGetLineFromAddrW64\n", GetCurrentThreadId()); foundline = SymGetLineFromAddrW64(g_currentProcess, programCounter, &displacement, &sourceInfo); + bool isFrameInternal = false; if (foundline && !showInternalFrames) { wcscpy_s(lowerCaseName, sourceInfo.FileName); _wcslwr_s(lowerCaseName, wcslen(lowerCaseName) + 1); - if (isInternalModule(lowerCaseName)) { + if (isInternalModule(lowerCaseName)) + { + isFrameInternal = true; // Don't show frames in files internal to the heap. g_symbolLock.Leave(); - continue; } } @@ -276,9 +283,10 @@ void CallStack::dump(BOOL showInternalFrames, UINT start_frame) const moduleName = callingModuleName; } - // Use static here to increase performance, and avoid heap allocs. Hopefully this won't - // prove to be an issue in thread safety. If it does, it will have to be simply non-static. - static WCHAR stack_line[MAXREPORTLENGTH + 1] = L""; + if (!isFrameInternal && isPrevFrameInternal) + Print(stack_line); + isPrevFrameInternal = isFrameInternal; + int NumChars = -1; // Display the current stack frame's information. if (foundline) { @@ -298,7 +306,8 @@ void CallStack::dump(BOOL showInternalFrames, UINT start_frame) const programCounter, moduleName, functionName, (DWORD)displacement64); } - Print(stack_line); + if (!isFrameInternal) + Print(stack_line); } } @@ -511,11 +520,14 @@ bool CallStack::isInternalModule( const PWSTR filename ) const wcsstr(filename, L"\\crt\\src\\dbgmalloc.c") || wcsstr(filename, L"\\crt\\src\\new.cpp") || wcsstr(filename, L"\\crt\\src\\newaop.cpp") || + wcsstr(filename, L"\\crt\\src\\dbgnew.cpp") || wcsstr(filename, L"\\crt\\src\\dbgcalloc.c") || wcsstr(filename, L"\\crt\\src\\realloc.c") || wcsstr(filename, L"\\crt\\src\\dbgrealloc.c") || wcsstr(filename, L"\\crt\\src\\dbgdel.cp") || wcsstr(filename, L"\\crt\\src\\free.c") || + wcsstr(filename, L"\\crt\\src\\strdup.c") || + wcsstr(filename, L"\\crt\\src\\wcsdup.c") || wcsstr(filename, L"\\vc\\include\\xmemory0"); } diff --git a/tests/basics/Allocs.cpp b/tests/basics/Allocs.cpp index bd5ae7be..b14aef8e 100644 --- a/tests/basics/Allocs.cpp +++ b/tests/basics/Allocs.cpp @@ -7,148 +7,153 @@ void AllocF(LeakOption type, bool bFree) { - int* leaked_memory = NULL; - int* leaked_memory_dbg = NULL; - if (type == eMalloc) - { - leaked_memory = (int*)malloc(78); - leaked_memory_dbg = (int*)_malloc_dbg(80, _NORMAL_BLOCK,__FILE__,__LINE__); - if (bFree) - { - free(leaked_memory); - _free_dbg(leaked_memory_dbg,_NORMAL_BLOCK); - } - } - else if (type == eNew) - { - leaked_memory = new int(4); - leaked_memory_dbg = new (_NORMAL_BLOCK, __FILE__, __LINE__) int(7); - if (bFree) - { - delete leaked_memory; - delete leaked_memory_dbg; - } - } - else if (type == eNewArray) - { - leaked_memory = new int[3]; - leaked_memory_dbg = new (_NORMAL_BLOCK,__FILE__,__LINE__) int[4]; + int* leaked_memory = NULL; + int* leaked_memory_dbg = NULL; + if (type == eMalloc) + { + leaked_memory = (int*)malloc(78); + leaked_memory_dbg = (int*)_malloc_dbg(80, _NORMAL_BLOCK,__FILE__,__LINE__); + if (bFree) + { + free(leaked_memory); + _free_dbg(leaked_memory_dbg,_NORMAL_BLOCK); + } + } + else if (type == eNew) + { + leaked_memory = new int(4); + leaked_memory_dbg = new (_NORMAL_BLOCK, __FILE__, __LINE__) int(7); + if (bFree) + { + delete leaked_memory; + delete leaked_memory_dbg; + } + } + else if (type == eNewArray) + { + leaked_memory = new int[3]; + leaked_memory_dbg = new (_NORMAL_BLOCK,__FILE__,__LINE__) int[4]; - // placement new operator - int temp[3]; - void* place = temp; - float* placed_mem = new (place) float[3]; // doesn't work. Nothing gets patched by vld - if (bFree) - { - delete [] leaked_memory; - delete [] leaked_memory_dbg; - } - } - else if (type == eCalloc) - { - leaked_memory = (int*)calloc(47,sizeof(int)); - leaked_memory_dbg = (int*)_calloc_dbg(39, sizeof(int), _NORMAL_BLOCK, __FILE__, __LINE__); - if (bFree) - { - free(leaked_memory); - _free_dbg(leaked_memory_dbg,_NORMAL_BLOCK); - } - } - else if (type == eRealloc) - { - int* temp = (int*)malloc(17); - leaked_memory = (int*)realloc(temp, 23); - leaked_memory = (int*)_recalloc(leaked_memory, 1, 31); - int* temp_dbg = (int*)malloc(9); - leaked_memory_dbg = (int*)_realloc_dbg(temp_dbg, 21, _NORMAL_BLOCK, __FILE__, __LINE__); - if (bFree) - { - free(leaked_memory); - _free_dbg(leaked_memory_dbg,_NORMAL_BLOCK); - } - } - else if (type == eCoTaskMem) - { - void* leaked = CoTaskMemAlloc(7); - void* realloced = CoTaskMemRealloc(leaked, 29); - if (bFree) - { - CoTaskMemFree(realloced); - } - } - else if (type == eAlignedMalloc) - { - void* leaked = _aligned_offset_malloc(64, 16, 1); - leaked_memory = (int*)_aligned_malloc(64, 16); - leaked_memory_dbg = (int*)_aligned_malloc_dbg(32, 16, __FILE__, __LINE__); - if (bFree) - { - _aligned_free(leaked); - _aligned_free(leaked_memory); - _aligned_free_dbg(leaked_memory_dbg); - } - } - else if (type == eAlignedRealloc) - { - void* leaked = _aligned_offset_malloc(64, 16, 1); - leaked_memory = (int*)_aligned_malloc(64, 16); - leaked_memory_dbg = (int*)_aligned_malloc_dbg(32, 16, __FILE__, __LINE__); - leaked = (int*)_aligned_offset_realloc(leaked, 48, 16, 2); - leaked_memory = (int*)_aligned_realloc(leaked_memory, 128, 16); - leaked_memory_dbg = (int*)_aligned_realloc_dbg(leaked_memory_dbg, 48, 16, __FILE__, __LINE__); - leaked = (int*)_aligned_offset_recalloc(leaked, 1, 52, 16, 2); - leaked_memory = (int*)_aligned_recalloc(leaked_memory, 1, 132, 16); - leaked_memory_dbg = (int*)_aligned_recalloc_dbg(leaked_memory_dbg, 1, 64, 16, __FILE__, __LINE__); - if (bFree) - { - _aligned_free(leaked); - _aligned_free(leaked_memory); - _aligned_free_dbg(leaked_memory_dbg); - } - } - else if (type == eStrdup) - { - leaked_memory = (int*)strdup("strdup() leaks!"); - leaked_memory_dbg = (int*)_strdup_dbg("_strdup_dbg() leaks!", _NORMAL_BLOCK,__FILE__,__LINE__); - void* leaked_wmemory = (int*)wcsdup(L"wcsdup() leaks!"); - void* leaked_wmemory_dbg = (int*)_wcsdup_dbg(L"_wcsdup_dbg() leaks!", _NORMAL_BLOCK,__FILE__,__LINE__); - if (bFree) - { - free(leaked_memory); - _free_dbg(leaked_memory_dbg,_NORMAL_BLOCK); - free(leaked_wmemory); - _free_dbg(leaked_wmemory_dbg,_NORMAL_BLOCK); - } - } + // placement new operator + int temp[3]; + void* place = temp; + float* placed_mem = new (place) float[3]; // doesn't work. Nothing gets patched by vld + if (bFree) + { + delete [] leaked_memory; + delete [] leaked_memory_dbg; + } + } + else if (type == eCalloc) + { + leaked_memory = (int*)calloc(47,sizeof(int)); + leaked_memory_dbg = (int*)_calloc_dbg(39, sizeof(int), _NORMAL_BLOCK, __FILE__, __LINE__); + if (bFree) + { + free(leaked_memory); + _free_dbg(leaked_memory_dbg,_NORMAL_BLOCK); + } + } + else if (type == eRealloc) + { + int* temp = (int*)malloc(17); + leaked_memory = (int*)realloc(temp, 23); + leaked_memory = (int*)_recalloc(leaked_memory, 1, 31); + int* temp_dbg = (int*)malloc(9); + leaked_memory_dbg = (int*)_realloc_dbg(temp_dbg, 21, _NORMAL_BLOCK, __FILE__, __LINE__); + if (bFree) + { + free(leaked_memory); + _free_dbg(leaked_memory_dbg,_NORMAL_BLOCK); + } + } + else if (type == eCoTaskMem) + { + void* leaked = CoTaskMemAlloc(7); + if (bFree) + { + CoTaskMemFree(leaked); + } + void* leaked2 = CoTaskMemAlloc(7); + void* realloced = CoTaskMemRealloc(leaked2, 29); + if (bFree) + { + CoTaskMemFree(realloced); + } + } + else if (type == eAlignedMalloc) + { + void* leaked = _aligned_offset_malloc(64, 16, 1); + leaked_memory = (int*)_aligned_malloc(64, 16); + leaked_memory_dbg = (int*)_aligned_malloc_dbg(32, 16, __FILE__, __LINE__); + if (bFree) + { + _aligned_free(leaked); + _aligned_free(leaked_memory); + _aligned_free_dbg(leaked_memory_dbg); + } + } + else if (type == eAlignedRealloc) + { + void* leaked = _aligned_offset_malloc(64, 16, 1); + leaked_memory = (int*)_aligned_malloc(64, 16); + leaked_memory_dbg = (int*)_aligned_malloc_dbg(32, 16, __FILE__, __LINE__); + leaked = (int*)_aligned_offset_realloc(leaked, 48, 16, 2); + leaked_memory = (int*)_aligned_realloc(leaked_memory, 128, 16); + leaked_memory_dbg = (int*)_aligned_realloc_dbg(leaked_memory_dbg, 48, 16, __FILE__, __LINE__); + leaked = (int*)_aligned_offset_recalloc(leaked, 1, 52, 16, 2); + leaked_memory = (int*)_aligned_recalloc(leaked_memory, 1, 132, 16); + leaked_memory_dbg = (int*)_aligned_recalloc_dbg(leaked_memory_dbg, 1, 64, 16, __FILE__, __LINE__); + if (bFree) + { + _aligned_free(leaked); + _aligned_free(leaked_memory); + _aligned_free_dbg(leaked_memory_dbg); + } + } + else if (type == eStrdup) + { + leaked_memory = (int*)strdup("strdup() leaks!"); + leaked_memory_dbg = (int*)_strdup_dbg("_strdup_dbg() leaks!", _NORMAL_BLOCK,__FILE__,__LINE__); + void* leaked_wmemory = (int*)wcsdup(L"wcsdup() leaks!"); + void* leaked_wmemory_dbg = (int*)_wcsdup_dbg(L"_wcsdup_dbg() leaks!", _NORMAL_BLOCK,__FILE__,__LINE__); + if (bFree) + { + free(leaked_memory); + _free_dbg(leaked_memory_dbg,_NORMAL_BLOCK); + free(leaked_wmemory); + _free_dbg(leaked_wmemory_dbg,_NORMAL_BLOCK); + } + } } void AllocE(LeakOption type, bool bFree) { - AllocF(type, bFree); + AllocF(type, bFree); } void AllocD(LeakOption type, bool bFree) { - AllocE(type, bFree); + AllocE(type, bFree); } void AllocC(LeakOption type, bool bFree) { - AllocD(type, bFree); + AllocD(type, bFree); } void AllocB(LeakOption type, bool bFree) { - AllocC(type, bFree); + AllocC(type, bFree); } void AllocA(LeakOption type, bool bFree) { - AllocB(type, bFree); + AllocB(type, bFree); } void Alloc(LeakOption type, bool bFree) { - AllocA(type, bFree); + AllocA(type, bFree); } \ No newline at end of file diff --git a/tests/basics/basics.cpp b/tests/basics/basics.cpp index 555f38c1..bb2d583a 100644 --- a/tests/basics/basics.cpp +++ b/tests/basics/basics.cpp @@ -99,7 +99,7 @@ namespace tut int prev = (int)VLDGetLeaksCount(); LeakMemory(eCoTaskMem,repeat,false); int leaks = (int)VLDGetLeaksCount() - prev; - ensure("leaks", leaks == (repeat * 1)); + ensure("leaks", leaks == (repeat * 2)); } template<> @@ -222,7 +222,7 @@ int _tmain(int argc, _TCHAR* argv[]) else if (_tcsicmp(_T("CoTaskMem"), argv[1]) == 0) { leak_type = eCoTaskMem; - multiplayer = 1; + multiplayer = 2; } else if (_tcsicmp(_T("AlignedMalloc"), argv[1]) == 0) { @@ -242,7 +242,7 @@ int _tmain(int argc, _TCHAR* argv[]) else if (_tcsicmp(_T("all"), argv[1]) == 0) { checkAll = true; - multiplayer = 21; + multiplayer = 22; } else { diff --git a/tests/basics/stdafx.h b/tests/basics/stdafx.h index 686c8f5b..b005a839 100644 --- a/tests/basics/stdafx.h +++ b/tests/basics/stdafx.h @@ -9,7 +9,6 @@ #include #include -#include diff --git a/tests/dynamic_dll/dllmain.cpp b/tests/dynamic_dll/dllmain.cpp index 69b58914..5ebd4cc1 100644 --- a/tests/dynamic_dll/dllmain.cpp +++ b/tests/dynamic_dll/dllmain.cpp @@ -4,16 +4,15 @@ BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved - ) + ) { - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; } - diff --git a/vld_hooks.cpp b/vld_hooks.cpp index 23ddf730..45b3df16 100644 --- a/vld_hooks.cpp +++ b/vld_hooks.cpp @@ -1911,6 +1911,13 @@ LPVOID VisualLeakDetector::_CoTaskMemAlloc (SIZE_T size) HMODULE ole32; tls_t *tls = g_vld.getTls(); + if (pCoTaskMemAlloc == NULL) { + // This is the first call to this function. Link to the real + // CoTaskMemAlloc. + ole32 = GetModuleHandleW(L"ole32.dll"); + pCoTaskMemAlloc = (CoTaskMemAlloc_t)g_vld._RGetProcAddress(ole32, "CoTaskMemAlloc"); + } + bool firstcall = (tls->context.fp == 0x0); if (firstcall) { // This is the first call to enter VLD for the current allocation. @@ -1920,13 +1927,6 @@ LPVOID VisualLeakDetector::_CoTaskMemAlloc (SIZE_T size) tls->blockProcessed = FALSE; } - if (pCoTaskMemAlloc == NULL) { - // This is the first call to this function. Link to the real - // CoTaskMemAlloc. - ole32 = GetModuleHandleW(L"ole32.dll"); - pCoTaskMemAlloc = (CoTaskMemAlloc_t)g_vld._RGetProcAddress(ole32, "CoTaskMemAlloc"); - } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. block = pCoTaskMemAlloc(size); @@ -1958,6 +1958,13 @@ LPVOID VisualLeakDetector::_CoTaskMemRealloc (LPVOID mem, SIZE_T size) HMODULE ole32; tls_t *tls = g_vld.getTls(); + if (pCoTaskMemRealloc == NULL) { + // This is the first call to this function. Link to the real + // CoTaskMemRealloc. + ole32 = GetModuleHandleW(L"ole32.dll"); + pCoTaskMemRealloc = (CoTaskMemRealloc_t)g_vld._RGetProcAddress(ole32, "CoTaskMemRealloc"); + } + bool firstcall = (tls->context.fp == 0x0); if (firstcall) { // This is the first call to enter VLD for the current allocation. @@ -1967,13 +1974,6 @@ LPVOID VisualLeakDetector::_CoTaskMemRealloc (LPVOID mem, SIZE_T size) tls->blockProcessed = FALSE; } - if (pCoTaskMemRealloc == NULL) { - // This is the first call to this function. Link to the real - // CoTaskMemRealloc. - ole32 = GetModuleHandleW(L"ole32.dll"); - pCoTaskMemRealloc = (CoTaskMemRealloc_t)g_vld._RGetProcAddress(ole32, "CoTaskMemRealloc"); - } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. block = pCoTaskMemRealloc(mem, size);