diff --git a/AUTHORS.txt b/AUTHORS.txt index ec5acdce..b70e762d 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -4,7 +4,7 @@ chrisJohnson http://www.codeplex.com/site/users/view/chrisJohnson Contributors: (listed alphabetically) ------------------------------------------------ -geordi, jerker_back, Laurent Lessieux (llessieux), snakefoot, VictorKharkov +benpmorgan, geordi, jerker_back, Laurent Lessieux (llessieux), snakefoot, VictorKharkov, xpol Many thanks to everyone who supported development without having svn write access. diff --git a/CHANGES.txt b/CHANGES.txt index de4b935b..af23df28 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,27 @@ -Visual Leak Detector (VLD) Version 2.2 +Visual Leak Detector (VLD) Version 2.2.2 Change Log / Release Notes +2.2.2 (18 December 2011) +---------------------------- + Bugs Fixed: + + Memory leaks with static linking fixed. + + Visual Studio C++ 2008/2010 Express Edition compilation fixed. + + Hang fixed with GetOpenFileName(). + +2.2.1 (22 November 2011) +---------------------------- + Enhancements: + + strdup and _wcsdup functions support added. + + Preliminary support for VS 11 added. + + Bugs Fixed: + + Low performance after upgrading from VLD v2.1. + + Runtime error R6002 fixed because of wrong memory dump format. + + version.h fixed in installer. + + Some PVS studio warning fixed. + 2.2 (21 Jule 2011) ---------------------------- Enhancements: diff --git a/callstack.cpp b/callstack.cpp index b4f0daba..3a6e2e20 100644 --- a/callstack.cpp +++ b/callstack.cpp @@ -40,51 +40,51 @@ extern VisualLeakDetector g_vld; // CallStack::CallStack () { - m_capacity = CALLSTACK_CHUNK_SIZE; - m_size = 0; - m_status = 0x0; - m_store.next = NULL; - m_topChunk = &m_store; - m_topIndex = 0; - m_resolved = NULL; - m_resolvedCapacity = 0; - m_resolvedLength = 0; + m_capacity = CALLSTACK_CHUNK_SIZE; + m_size = 0; + m_status = 0x0; + m_store.next = NULL; + m_topChunk = &m_store; + m_topIndex = 0; + m_resolved = NULL; + m_resolvedCapacity = 0; + m_resolvedLength = 0; } // Destructor - Frees all memory allocated to the CallStack. // CallStack::~CallStack () { - CallStack::chunk_t *chunk = m_store.next; - CallStack::chunk_t *temp; - - while (chunk) { - temp = chunk; - chunk = temp->next; - delete temp; - } - - if (m_resolved) - { - delete [] m_resolved; - } - - m_resolved = NULL; - m_resolvedCapacity = 0; - m_resolvedLength = 0; + CallStack::chunk_t *chunk = m_store.next; + CallStack::chunk_t *temp; + + while (chunk) { + temp = chunk; + chunk = temp->next; + delete temp; + } + + if (m_resolved) + { + delete [] m_resolved; + } + + m_resolved = NULL; + m_resolvedCapacity = 0; + m_resolvedLength = 0; } CallStack* CallStack::Create() { - CallStack* result = NULL; - if (g_vld.GetOptions() & VLD_OPT_SAFE_STACK_WALK) { - result = new SafeCallStack(); - } - else { - result = new FastCallStack(); - } - return result; - + CallStack* result = NULL; + if (g_vld.GetOptions() & VLD_OPT_SAFE_STACK_WALK) { + result = new SafeCallStack(); + } + else { + result = new FastCallStack(); + } + return result; + } // operator == - Equality operator. Compares the CallStack to another CallStack // for equality. Two CallStacks are equal if they are the same size and if @@ -99,31 +99,31 @@ CallStack* CallStack::Create() // BOOL CallStack::operator == (const CallStack &other) const { - if (m_size != other.m_size) { - // They can't be equal if the sizes are different. - return FALSE; - } - - // Walk the chunk list and within each chunk walk the frames array until we - // either find a mismatch, or until we reach the end of the call stacks. - const CallStack::chunk_t *prevChunk = NULL; - const CallStack::chunk_t *chunk = &m_store; - const CallStack::chunk_t *otherChunk = &other.m_store; - while (prevChunk != m_topChunk) { - UINT32 size = (chunk == m_topChunk) ? m_topIndex : CALLSTACK_CHUNK_SIZE; - for (UINT32 index = 0; index < size; index++) { - if (chunk->frames[index] != otherChunk->frames[index]) { - // Found a mismatch. They are not equal. - return FALSE; - } - } - prevChunk = chunk; - chunk = chunk->next; - otherChunk = otherChunk->next; - } - - // Reached the end of the call stacks. They are equal. - return TRUE; + if (m_size != other.m_size) { + // They can't be equal if the sizes are different. + return FALSE; + } + + // Walk the chunk list and within each chunk walk the frames array until we + // either find a mismatch, or until we reach the end of the call stacks. + const CallStack::chunk_t *prevChunk = NULL; + const CallStack::chunk_t *chunk = &m_store; + const CallStack::chunk_t *otherChunk = &other.m_store; + while (prevChunk != m_topChunk) { + UINT32 size = (chunk == m_topChunk) ? m_topIndex : CALLSTACK_CHUNK_SIZE; + for (UINT32 index = 0; index < size; index++) { + if (chunk->frames[index] != otherChunk->frames[index]) { + // Found a mismatch. They are not equal. + return FALSE; + } + } + prevChunk = chunk; + chunk = chunk->next; + otherChunk = otherChunk->next; + } + + // Reached the end of the call stacks. They are equal. + return TRUE; } // operator [] - Random access operator. Retrieves the frame at the specified @@ -145,14 +145,14 @@ BOOL CallStack::operator == (const CallStack &other) const // UINT_PTR CallStack::operator [] (UINT32 index) const { - UINT32 chunknumber = index / CALLSTACK_CHUNK_SIZE; - const CallStack::chunk_t *chunk = &m_store; + UINT32 chunknumber = index / CALLSTACK_CHUNK_SIZE; + const CallStack::chunk_t *chunk = &m_store; - for (UINT32 count = 0; count < chunknumber; count++) { - chunk = chunk->next; - } + for (UINT32 count = 0; count < chunknumber; count++) { + chunk = chunk->next; + } - return chunk->frames[index % CALLSTACK_CHUNK_SIZE]; + return chunk->frames[index % CALLSTACK_CHUNK_SIZE]; } // clear - Resets the CallStack, returning it to a state where no frames have @@ -168,16 +168,16 @@ UINT_PTR CallStack::operator [] (UINT32 index) const // VOID CallStack::clear () { - m_size = 0; - m_topChunk = &m_store; - m_topIndex = 0; - if (m_resolved) - { - delete [] m_resolved; - m_resolved = NULL; - } - m_resolvedCapacity = 0; - m_resolvedLength = 0; + m_size = 0; + m_topChunk = &m_store; + m_topIndex = 0; + if (m_resolved) + { + delete [] m_resolved; + m_resolved = NULL; + } + m_resolvedCapacity = 0; + m_resolvedLength = 0; } @@ -196,108 +196,110 @@ VOID CallStack::clear () // void CallStack::dump(BOOL showInternalFrames, UINT start_frame) const { - // The stack was dumped already - if (m_resolved) - { - dumpResolved(); - return; - } - - if (m_status & CALLSTACK_STATUS_INCOMPLETE) { - // This call stack appears to be incomplete. Using StackWalk64 may be - // more reliable. - Report(L" HINT: The following call stack may be incomplete. Setting \"StackWalkMethod\"\n" - L" in the vld.ini file to \"safe\" instead of \"fast\" may result in a more\n" - L" complete stack trace.\n"); - } - - IMAGEHLP_LINE64 sourceInfo = { 0 }; - sourceInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64); - - BYTE symbolBuffer [sizeof(SYMBOL_INFO) + MAX_SYMBOL_NAME_SIZE] = { 0 }; - - WCHAR lowerCaseName [MAX_PATH]; - WCHAR callingModuleName [MAX_PATH]; - - const size_t max_size = MAXREPORTLENGTH + 1; - - // Iterate through each frame in the call stack. - for (UINT32 frame = start_frame; frame < m_size; frame++) - { - // Try to get the source file and line number associated with - // this program counter address. - SIZE_T programCounter = (*this)[frame]; - g_symbolLock.Enter(); - BOOL foundline = FALSE; - DWORD displacement = 0; - foundline = SymGetLineFromAddrW64(g_currentProcess, programCounter, &displacement, &sourceInfo); - if (foundline && !showInternalFrames) { - wcscpy_s(lowerCaseName, sourceInfo.FileName); - _wcslwr_s(lowerCaseName, wcslen(lowerCaseName) + 1); - if (isInternalModule(lowerCaseName)) { - // Don't show frames in files internal to the heap. - g_symbolLock.Leave(); - continue; - } - } - - // Initialize structures passed to the symbol handler. - SYMBOL_INFO* functionInfo = (SYMBOL_INFO*)&symbolBuffer; - functionInfo->SizeOfStruct = sizeof(SYMBOL_INFO); - functionInfo->MaxNameLen = MAX_SYMBOL_NAME_LENGTH; - - // Try to get the name of the function containing this program - // counter address. - DWORD64 displacement64 = 0; - LPWSTR functionName; - if (SymFromAddrW(g_currentProcess, programCounter, &displacement64, functionInfo)) { - functionName = functionInfo->Name; - } - else { - // GetFormattedMessage( GetLastError() ); - functionName = L"(Function name unavailable)"; - displacement64 = 0; - } - g_symbolLock.Leave(); - - HMODULE hCallingModule = GetCallingModule(programCounter); - LPWSTR moduleName = L"(Module name unavailable)"; - if (hCallingModule && - GetModuleFileName(hCallingModule, callingModuleName, _countof(callingModuleName)) > 0) - { - moduleName = wcsrchr(callingModuleName, L'\\'); - if (moduleName == NULL) - moduleName = wcsrchr(callingModuleName, L'/'); - if (moduleName != NULL) - moduleName++; - else - 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""; - int NumChars = -1; - // Display the current stack frame's information. - if (foundline) { - if (displacement == 0) - NumChars = _snwprintf_s(stack_line, max_size, _TRUNCATE, L" %s (%d): %s!%s\n", - sourceInfo.FileName, sourceInfo.LineNumber, moduleName, functionName); - else - NumChars = _snwprintf_s(stack_line, max_size, _TRUNCATE, L" %s (%d): %s!%s + 0x%X bytes\n", - sourceInfo.FileName, sourceInfo.LineNumber, moduleName, functionName, displacement); - } - else { - if (displacement64 == 0) - NumChars = _snwprintf_s(stack_line, max_size, _TRUNCATE, L" " ADDRESSFORMAT L" (File and line number not available): %s!%s\n", - programCounter, moduleName, functionName); - else - NumChars = _snwprintf_s(stack_line, max_size, _TRUNCATE, L" " ADDRESSFORMAT L" (File and line number not available): %s!%s + 0x%X bytes\n", - programCounter, moduleName, functionName, (DWORD)displacement64); - } - - Print(stack_line); - } + // The stack was dumped already + if (m_resolved) + { + dumpResolved(); + return; + } + + if (m_status & CALLSTACK_STATUS_INCOMPLETE) { + // This call stack appears to be incomplete. Using StackWalk64 may be + // more reliable. + Report(L" HINT: The following call stack may be incomplete. Setting \"StackWalkMethod\"\n" + L" in the vld.ini file to \"safe\" instead of \"fast\" may result in a more\n" + L" complete stack trace.\n"); + } + + IMAGEHLP_LINE64 sourceInfo = { 0 }; + sourceInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + + BYTE symbolBuffer [sizeof(SYMBOL_INFO) + MAX_SYMBOL_NAME_SIZE] = { 0 }; + + WCHAR lowerCaseName [MAX_PATH]; + WCHAR callingModuleName [MAX_PATH]; + + const size_t max_size = MAXREPORTLENGTH + 1; + + // Iterate through each frame in the call stack. + for (UINT32 frame = start_frame; frame < m_size; frame++) + { + // Try to get the source file and line number associated with + // this program counter address. + SIZE_T programCounter = (*this)[frame]; + g_symbolLock.Enter(); + BOOL foundline = FALSE; + DWORD displacement = 0; + DbgTrace(L"dbghelp32.dll %i: SymGetLineFromAddrW64\n", GetCurrentThreadId()); + foundline = SymGetLineFromAddrW64(g_currentProcess, programCounter, &displacement, &sourceInfo); + if (foundline && !showInternalFrames) { + wcscpy_s(lowerCaseName, sourceInfo.FileName); + _wcslwr_s(lowerCaseName, wcslen(lowerCaseName) + 1); + if (isInternalModule(lowerCaseName)) { + // Don't show frames in files internal to the heap. + g_symbolLock.Leave(); + continue; + } + } + + // Initialize structures passed to the symbol handler. + SYMBOL_INFO* functionInfo = (SYMBOL_INFO*)&symbolBuffer; + functionInfo->SizeOfStruct = sizeof(SYMBOL_INFO); + functionInfo->MaxNameLen = MAX_SYMBOL_NAME_LENGTH; + + // Try to get the name of the function containing this program + // counter address. + DWORD64 displacement64 = 0; + LPWSTR functionName; + DbgTrace(L"dbghelp32.dll %i: SymFromAddrW\n", GetCurrentThreadId()); + if (SymFromAddrW(g_currentProcess, programCounter, &displacement64, functionInfo)) { + functionName = functionInfo->Name; + } + else { + // GetFormattedMessage( GetLastError() ); + functionName = L"(Function name unavailable)"; + displacement64 = 0; + } + g_symbolLock.Leave(); + + HMODULE hCallingModule = GetCallingModule(programCounter); + LPWSTR moduleName = L"(Module name unavailable)"; + if (hCallingModule && + GetModuleFileName(hCallingModule, callingModuleName, _countof(callingModuleName)) > 0) + { + moduleName = wcsrchr(callingModuleName, L'\\'); + if (moduleName == NULL) + moduleName = wcsrchr(callingModuleName, L'/'); + if (moduleName != NULL) + moduleName++; + else + 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""; + int NumChars = -1; + // Display the current stack frame's information. + if (foundline) { + if (displacement == 0) + NumChars = _snwprintf_s(stack_line, max_size, _TRUNCATE, L" %s (%d): %s!%s\n", + sourceInfo.FileName, sourceInfo.LineNumber, moduleName, functionName); + else + NumChars = _snwprintf_s(stack_line, max_size, _TRUNCATE, L" %s (%d): %s!%s + 0x%X bytes\n", + sourceInfo.FileName, sourceInfo.LineNumber, moduleName, functionName, displacement); + } + else { + if (displacement64 == 0) + NumChars = _snwprintf_s(stack_line, max_size, _TRUNCATE, L" " ADDRESSFORMAT L" (File and line number not available): %s!%s\n", + programCounter, moduleName, functionName); + else + NumChars = _snwprintf_s(stack_line, max_size, _TRUNCATE, L" " ADDRESSFORMAT L" (File and line number not available): %s!%s + 0x%X bytes\n", + programCounter, moduleName, functionName, (DWORD)displacement64); + } + + Print(stack_line); + } } // Resolve - Creates a nicely formatted rendition of the CallStack, including @@ -316,130 +318,132 @@ void CallStack::dump(BOOL showInternalFrames, UINT start_frame) const // void CallStack::resolve(BOOL showInternalFrames) { - if (m_resolved) - { - // already resolved, no need to do it again - // resolving twice may report an incorrect module for the stack frames - // if the memory was leaked in a dynamic library that was already unloaded. - return; - } - if (m_status & CALLSTACK_STATUS_INCOMPLETE) { - // This call stack appears to be incomplete. Using StackWalk64 may be - // more reliable. - Report(L" HINT: The following call stack may be incomplete. Setting \"StackWalkMethod\"\n" - L" in the vld.ini file to \"safe\" instead of \"fast\" may result in a more\n" - L" complete stack trace.\n"); - } - - IMAGEHLP_LINE64 sourceInfo = { 0 }; - sourceInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64); - - BYTE symbolBuffer [sizeof(SYMBOL_INFO) + MAX_SYMBOL_NAME_SIZE] = { 0 }; - - WCHAR callingModuleName [MAX_PATH] = L""; - WCHAR lowerCaseName [MAX_PATH]; - - const size_t max_line_length = MAXREPORTLENGTH + 1; - m_resolvedCapacity = m_size * max_line_length; - m_resolved = new WCHAR[m_resolvedCapacity]; - const size_t allocedBytes = m_resolvedCapacity * sizeof(WCHAR); - ZeroMemory(m_resolved, allocedBytes); - - // Iterate through each frame in the call stack. - for (UINT32 frame = 0; frame < m_size; frame++) - { - // Try to get the source file and line number associated with - // this program counter address. - SIZE_T programCounter = (*this)[frame]; - g_symbolLock.Enter(); - BOOL foundline = FALSE; - DWORD displacement = 0; - - // It turns out that calls to SymGetLineFromAddrW64 may free the very memory we are scrutinizing here - // in this method. If this is the case, m_Resolved will be null after SymGetLineFromAddrW64 returns. - // When that happens there is nothing we can do except crash. - foundline = SymGetLineFromAddrW64(g_currentProcess, programCounter, &displacement, &sourceInfo); - assert(m_resolved != NULL); - - if (foundline && !showInternalFrames) { - wcscpy_s(lowerCaseName, sourceInfo.FileName); - _wcslwr_s(lowerCaseName, wcslen(lowerCaseName) + 1); - if (isInternalModule(lowerCaseName)) { - // Don't show frames in files internal to the heap. - g_symbolLock.Leave(); - continue; - } - } - - // Initialize structures passed to the symbol handler. - SYMBOL_INFO* functionInfo = (SYMBOL_INFO*)&symbolBuffer; - functionInfo->SizeOfStruct = sizeof(SYMBOL_INFO); - functionInfo->MaxNameLen = MAX_SYMBOL_NAME_LENGTH; - - // Try to get the name of the function containing this program - // counter address. - DWORD64 displacement64 = 0; - LPWSTR functionName; - if (SymFromAddrW(g_currentProcess, programCounter, &displacement64, functionInfo)) { - functionName = functionInfo->Name; - } - else { - // GetFormattedMessage( GetLastError() ); - functionName = L"(Function name unavailable)"; - displacement64 = 0; - } - g_symbolLock.Leave(); - - HMODULE hCallingModule = GetCallingModule(programCounter); - LPWSTR moduleName = L"(Module name unavailable)"; - if (hCallingModule && - GetModuleFileName(hCallingModule, callingModuleName, _countof(callingModuleName)) > 0) - { - moduleName = wcsrchr(callingModuleName, L'\\'); - if (moduleName == NULL) - moduleName = wcsrchr(callingModuleName, L'/'); - if (moduleName != NULL) - moduleName++; - else - 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[max_line_length] = L""; - int NumChars = -1; - // Display the current stack frame's information. - if (foundline) { - // Just truncate anything that is too long. - if (displacement == 0) - NumChars = _snwprintf_s(stack_line, max_line_length, _TRUNCATE, L" %s (%d): %s!%s\n", - sourceInfo.FileName, sourceInfo.LineNumber, moduleName, functionName); - else - NumChars = _snwprintf_s(stack_line, max_line_length, _TRUNCATE, L" %s (%d): %s!%s + 0x%X bytes\n", - sourceInfo.FileName, sourceInfo.LineNumber, moduleName, functionName, displacement); - } - else { - if (displacement64 == 0) - NumChars = _snwprintf_s(stack_line, max_line_length, _TRUNCATE, L" " ADDRESSFORMAT L" (File and line number not available): %s!%s\n", - programCounter, moduleName, functionName); - else - NumChars = _snwprintf_s(stack_line, max_line_length, _TRUNCATE, L" " ADDRESSFORMAT L" (File and line number not available): %s!%s + 0x%X bytes\n", - programCounter, moduleName, functionName, (DWORD)displacement64); - } - - if (NumChars >= 0) { - assert(m_resolved != NULL); - m_resolvedLength += NumChars; - wcsncat_s(m_resolved, m_resolvedCapacity, stack_line, NumChars); - } - } // end for loop + if (m_resolved) + { + // already resolved, no need to do it again + // resolving twice may report an incorrect module for the stack frames + // if the memory was leaked in a dynamic library that was already unloaded. + return; + } + if (m_status & CALLSTACK_STATUS_INCOMPLETE) { + // This call stack appears to be incomplete. Using StackWalk64 may be + // more reliable. + Report(L" HINT: The following call stack may be incomplete. Setting \"StackWalkMethod\"\n" + L" in the vld.ini file to \"safe\" instead of \"fast\" may result in a more\n" + L" complete stack trace.\n"); + } + + IMAGEHLP_LINE64 sourceInfo = { 0 }; + sourceInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + + BYTE symbolBuffer [sizeof(SYMBOL_INFO) + MAX_SYMBOL_NAME_SIZE] = { 0 }; + + WCHAR callingModuleName [MAX_PATH] = L""; + WCHAR lowerCaseName [MAX_PATH]; + + const size_t max_line_length = MAXREPORTLENGTH + 1; + m_resolvedCapacity = m_size * max_line_length; + m_resolved = new WCHAR[m_resolvedCapacity]; + const size_t allocedBytes = m_resolvedCapacity * sizeof(WCHAR); + ZeroMemory(m_resolved, allocedBytes); + + // Iterate through each frame in the call stack. + for (UINT32 frame = 0; frame < m_size; frame++) + { + // Try to get the source file and line number associated with + // this program counter address. + SIZE_T programCounter = (*this)[frame]; + g_symbolLock.Enter(); + BOOL foundline = FALSE; + DWORD displacement = 0; + + // It turns out that calls to SymGetLineFromAddrW64 may free the very memory we are scrutinizing here + // in this method. If this is the case, m_Resolved will be null after SymGetLineFromAddrW64 returns. + // When that happens there is nothing we can do except crash. + DbgTrace(L"dbghelp32.dll %i: SymGetLineFromAddrW64\n", GetCurrentThreadId()); + foundline = SymGetLineFromAddrW64(g_currentProcess, programCounter, &displacement, &sourceInfo); + assert(m_resolved != NULL); + + if (foundline && !showInternalFrames) { + wcscpy_s(lowerCaseName, sourceInfo.FileName); + _wcslwr_s(lowerCaseName, wcslen(lowerCaseName) + 1); + if (isInternalModule(lowerCaseName)) { + // Don't show frames in files internal to the heap. + g_symbolLock.Leave(); + continue; + } + } + + // Initialize structures passed to the symbol handler. + SYMBOL_INFO* functionInfo = (SYMBOL_INFO*)&symbolBuffer; + functionInfo->SizeOfStruct = sizeof(SYMBOL_INFO); + functionInfo->MaxNameLen = MAX_SYMBOL_NAME_LENGTH; + + // Try to get the name of the function containing this program + // counter address. + DWORD64 displacement64 = 0; + LPWSTR functionName; + DbgTrace(L"dbghelp32.dll %i: SymFromAddrW\n", GetCurrentThreadId()); + if (SymFromAddrW(g_currentProcess, programCounter, &displacement64, functionInfo)) { + functionName = functionInfo->Name; + } + else { + // GetFormattedMessage( GetLastError() ); + functionName = L"(Function name unavailable)"; + displacement64 = 0; + } + g_symbolLock.Leave(); + + HMODULE hCallingModule = GetCallingModule(programCounter); + LPWSTR moduleName = L"(Module name unavailable)"; + if (hCallingModule && + GetModuleFileName(hCallingModule, callingModuleName, _countof(callingModuleName)) > 0) + { + moduleName = wcsrchr(callingModuleName, L'\\'); + if (moduleName == NULL) + moduleName = wcsrchr(callingModuleName, L'/'); + if (moduleName != NULL) + moduleName++; + else + 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[max_line_length] = L""; + int NumChars = -1; + // Display the current stack frame's information. + if (foundline) { + // Just truncate anything that is too long. + if (displacement == 0) + NumChars = _snwprintf_s(stack_line, max_line_length, _TRUNCATE, L" %s (%d): %s!%s\n", + sourceInfo.FileName, sourceInfo.LineNumber, moduleName, functionName); + else + NumChars = _snwprintf_s(stack_line, max_line_length, _TRUNCATE, L" %s (%d): %s!%s + 0x%X bytes\n", + sourceInfo.FileName, sourceInfo.LineNumber, moduleName, functionName, displacement); + } + else { + if (displacement64 == 0) + NumChars = _snwprintf_s(stack_line, max_line_length, _TRUNCATE, L" " ADDRESSFORMAT L" (File and line number not available): %s!%s\n", + programCounter, moduleName, functionName); + else + NumChars = _snwprintf_s(stack_line, max_line_length, _TRUNCATE, L" " ADDRESSFORMAT L" (File and line number not available): %s!%s + 0x%X bytes\n", + programCounter, moduleName, functionName, (DWORD)displacement64); + } + + if (NumChars >= 0) { + assert(m_resolved != NULL); + m_resolvedLength += NumChars; + wcsncat_s(m_resolved, m_resolvedCapacity, stack_line, NumChars); + } + } // end for loop } // DumpResolve void CallStack::dumpResolved() const { - if (m_resolved) - Print(m_resolved); + if (m_resolved) + Print(m_resolved); } @@ -452,14 +456,14 @@ void CallStack::dumpResolved() const // DWORD CallStack::getHashValue () const { - DWORD hashcode = 0xD202EF8D; - - // Iterate through each frame in the call stack. - for (UINT32 frame = 0; frame < m_size; frame++) { - UINT_PTR programcounter = (*this)[frame]; - hashcode = CalculateCRC32(programcounter, hashcode); - } - return hashcode; + DWORD hashcode = 0xD202EF8D; + + // Iterate through each frame in the call stack. + for (UINT32 frame = 0; frame < m_size; frame++) { + UINT_PTR programcounter = (*this)[frame]; + hashcode = CalculateCRC32(programcounter, hashcode); + } + return hashcode; } // push_back - Pushes a frame's program counter onto the CallStack. Pushes are @@ -477,42 +481,42 @@ DWORD CallStack::getHashValue () const // VOID CallStack::push_back (const UINT_PTR programcounter) { - if (m_size == m_capacity) { - // At current capacity. Allocate additional storage. - CallStack::chunk_t *chunk = new CallStack::chunk_t; - chunk->next = NULL; - m_topChunk->next = chunk; - m_topChunk = chunk; - m_topIndex = 0; - m_capacity += CALLSTACK_CHUNK_SIZE; - } - else if (m_topIndex >= CALLSTACK_CHUNK_SIZE) { - // There is more capacity, but not in this chunk. Go to the next chunk. - // Note that this only happens if this CallStack has previously been - // cleared (clearing resets the data, but doesn't give up any allocated - // space). - m_topChunk = m_topChunk->next; - m_topIndex = 0; - } - - m_topChunk->frames[m_topIndex++] = programcounter; - m_size++; + if (m_size == m_capacity) { + // At current capacity. Allocate additional storage. + CallStack::chunk_t *chunk = new CallStack::chunk_t; + chunk->next = NULL; + m_topChunk->next = chunk; + m_topChunk = chunk; + m_topIndex = 0; + m_capacity += CALLSTACK_CHUNK_SIZE; + } + else if (m_topIndex >= CALLSTACK_CHUNK_SIZE) { + // There is more capacity, but not in this chunk. Go to the next chunk. + // Note that this only happens if this CallStack has previously been + // cleared (clearing resets the data, but doesn't give up any allocated + // space). + m_topChunk = m_topChunk->next; + m_topIndex = 0; + } + + m_topChunk->frames[m_topIndex++] = programcounter; + m_size++; } bool CallStack::isInternalModule( const PWSTR filename ) const { - return wcsstr(filename, L"\\crt\\src\\afxmem.cpp") || - wcsstr(filename, L"\\crt\\src\\dbgheap.c") || - wcsstr(filename, L"\\crt\\src\\malloc.c") || - 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\\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"\\vc\\include\\xmemory0"); + return wcsstr(filename, L"\\crt\\src\\afxmem.cpp") || + wcsstr(filename, L"\\crt\\src\\dbgheap.c") || + wcsstr(filename, L"\\crt\\src\\malloc.c") || + 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\\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"\\vc\\include\\xmemory0"); } // getStackTrace - Traces the stack as far back as possible, or until 'maxdepth' @@ -536,71 +540,71 @@ bool CallStack::isInternalModule( const PWSTR filename ) const // VOID FastCallStack::getStackTrace (UINT32 maxdepth, const context_t& context) { - UINT32 count = 0; - UINT_PTR* framePointer = context.fp; + UINT32 count = 0; + UINT_PTR* framePointer = context.fp; #if defined(_M_IX86) - while (count < maxdepth) { - if (*framePointer < (UINT_PTR)framePointer) { - if (*framePointer == NULL) { - // Looks like we reached the end of the stack. - break; - } - else { - // Invalid frame pointer. Frame pointer addresses should always - // increase as we move up the stack. - m_status |= CALLSTACK_STATUS_INCOMPLETE; - break; - } - } - if (*framePointer & (sizeof(UINT_PTR*) - 1)) { - // Invalid frame pointer. Frame pointer addresses should always - // be aligned to the size of a pointer. This probably means that - // we've encountered a frame that was created by a module built with - // frame pointer omission (FPO) optimization turned on. - m_status |= CALLSTACK_STATUS_INCOMPLETE; - break; - } - if (IsBadReadPtr((UINT*)*framePointer, sizeof(UINT_PTR*))) { - // Bogus frame pointer. Again, this probably means that we've - // encountered a frame built with FPO optimization. - m_status |= CALLSTACK_STATUS_INCOMPLETE; - break; - } - count++; - push_back(*(framePointer + 1)); - framePointer = (UINT_PTR*)*framePointer; - } + while (count < maxdepth) { + if (*framePointer < (UINT_PTR)framePointer) { + if (*framePointer == NULL) { + // Looks like we reached the end of the stack. + break; + } + else { + // Invalid frame pointer. Frame pointer addresses should always + // increase as we move up the stack. + m_status |= CALLSTACK_STATUS_INCOMPLETE; + break; + } + } + if (*framePointer & (sizeof(UINT_PTR*) - 1)) { + // Invalid frame pointer. Frame pointer addresses should always + // be aligned to the size of a pointer. This probably means that + // we've encountered a frame that was created by a module built with + // frame pointer omission (FPO) optimization turned on. + m_status |= CALLSTACK_STATUS_INCOMPLETE; + break; + } + if (IsBadReadPtr((UINT*)*framePointer, sizeof(UINT_PTR*))) { + // Bogus frame pointer. Again, this probably means that we've + // encountered a frame built with FPO optimization. + m_status |= CALLSTACK_STATUS_INCOMPLETE; + break; + } + count++; + push_back(*(framePointer + 1)); + framePointer = (UINT_PTR*)*framePointer; + } #elif defined(_M_X64) - UINT32 maxframes = min(62, maxdepth + 10); - static USHORT (WINAPI *s_pfnCaptureStackBackTrace)(ULONG FramesToSkip, ULONG FramesToCapture, PVOID* BackTrace, PULONG BackTraceHash) = 0; - if (s_pfnCaptureStackBackTrace == 0) - { - const HMODULE hNtDll = GetModuleHandleW(L"ntdll.dll"); - reinterpret_cast(s_pfnCaptureStackBackTrace) - = ::GetProcAddress(hNtDll, "RtlCaptureStackBackTrace"); - if (s_pfnCaptureStackBackTrace == 0) - return; - } - UINT_PTR* myFrames = new UINT_PTR[maxframes]; - ZeroMemory(myFrames, sizeof(UINT_PTR) * maxframes); - s_pfnCaptureStackBackTrace(0, maxframes, (PVOID*)myFrames, NULL); - UINT32 startIndex = 0; - while (count < maxframes) { - if (myFrames[count] == 0) - break; - if (myFrames[count] == *(framePointer + 1)) - startIndex = count; - count++; - } - count = startIndex; - while (count < maxframes) { - if (myFrames[count] == 0) - break; - push_back(myFrames[count]); - count++; - } - delete [] myFrames; + UINT32 maxframes = min(62, maxdepth + 10); + static USHORT (WINAPI *s_pfnCaptureStackBackTrace)(ULONG FramesToSkip, ULONG FramesToCapture, PVOID* BackTrace, PULONG BackTraceHash) = 0; + if (s_pfnCaptureStackBackTrace == 0) + { + const HMODULE hNtDll = GetModuleHandleW(L"ntdll.dll"); + reinterpret_cast(s_pfnCaptureStackBackTrace) + = ::GetProcAddress(hNtDll, "RtlCaptureStackBackTrace"); + if (s_pfnCaptureStackBackTrace == 0) + return; + } + UINT_PTR* myFrames = new UINT_PTR[maxframes]; + ZeroMemory(myFrames, sizeof(UINT_PTR) * maxframes); + s_pfnCaptureStackBackTrace(0, maxframes, (PVOID*)myFrames, NULL); + UINT32 startIndex = 0; + while (count < maxframes) { + if (myFrames[count] == 0) + break; + if (myFrames[count] == *(framePointer + 1)) + startIndex = count; + count++; + } + count = startIndex; + while (count < maxframes) { + if (myFrames[count] == 0) + break; + push_back(myFrames[count]); + count++; + } + delete [] myFrames; #endif } @@ -625,57 +629,58 @@ VOID FastCallStack::getStackTrace (UINT32 maxdepth, const context_t& context) // VOID SafeCallStack::getStackTrace (UINT32 maxdepth, const context_t& context) { - UINT_PTR* framePointer = context.fp; - DWORD architecture = X86X64ARCHITECTURE; - CONTEXT currentContext; - memset(¤tContext, 0, sizeof(currentContext)); + UINT_PTR* framePointer = context.fp; + DWORD architecture = X86X64ARCHITECTURE; + CONTEXT currentContext; + memset(¤tContext, 0, sizeof(currentContext)); - // Get the required values for initialization of the STACKFRAME64 structure - // to be passed to StackWalk64(). Required fields are AddrPC and AddrFrame. + // Get the required values for initialization of the STACKFRAME64 structure + // to be passed to StackWalk64(). Required fields are AddrPC and AddrFrame. #if defined(_M_IX86) - UINT_PTR programcounter = *(framePointer + 1); - UINT_PTR stackpointer = (*framePointer) - maxdepth * 10 * sizeof(void*); // An approximation. - currentContext.SPREG = stackpointer; - currentContext.BPREG = (DWORD64)framePointer; - currentContext.IPREG = programcounter; + UINT_PTR programcounter = *(framePointer + 1); + UINT_PTR stackpointer = (*framePointer) - maxdepth * 10 * sizeof(void*); // An approximation. + currentContext.SPREG = stackpointer; + currentContext.BPREG = (DWORD64)framePointer; + currentContext.IPREG = programcounter; #elif defined(_M_X64) - currentContext.SPREG = context.Rsp; - currentContext.BPREG = (DWORD64)framePointer; - currentContext.IPREG = context.Rip; + currentContext.SPREG = context.Rsp; + currentContext.BPREG = (DWORD64)framePointer; + currentContext.IPREG = context.Rip; #else - // If you want to retarget Visual Leak Detector to another processor - // architecture then you'll need to provide architecture-specific code to - // obtain the program counter and stack pointer from the given frame pointer. + // If you want to retarget Visual Leak Detector to another processor + // architecture then you'll need to provide architecture-specific code to + // obtain the program counter and stack pointer from the given frame pointer. #error "Visual Leak Detector is not supported on this architecture." #endif // _M_IX86 || _M_X64 - // Initialize the STACKFRAME64 structure. - STACKFRAME64 frame; - memset(&frame, 0x0, sizeof(frame)); - frame.AddrPC.Offset = currentContext.IPREG; - frame.AddrPC.Mode = AddrModeFlat; - frame.AddrStack.Offset = currentContext.SPREG; - frame.AddrStack.Mode = AddrModeFlat; - frame.AddrFrame.Offset = currentContext.BPREG; - frame.AddrFrame.Mode = AddrModeFlat; - frame.Virtual = TRUE; - - // Walk the stack. - CriticalSectionLocker cs(g_stackWalkLock); - UINT32 count = 0; - while (count < maxdepth) { - count++; - if (!StackWalk64(architecture, g_currentProcess, g_currentThread, &frame, ¤tContext, NULL, - SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { - // Couldn't trace back through any more frames. - break; - } - if (frame.AddrFrame.Offset == 0) { - // End of stack. - break; - } - - // Push this frame's program counter onto the CallStack. - push_back((UINT_PTR)frame.AddrPC.Offset); - } + // Initialize the STACKFRAME64 structure. + STACKFRAME64 frame; + memset(&frame, 0x0, sizeof(frame)); + frame.AddrPC.Offset = currentContext.IPREG; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrStack.Offset = currentContext.SPREG; + frame.AddrStack.Mode = AddrModeFlat; + frame.AddrFrame.Offset = currentContext.BPREG; + frame.AddrFrame.Mode = AddrModeFlat; + frame.Virtual = TRUE; + + // Walk the stack. + CriticalSectionLocker cs(g_stackWalkLock); + UINT32 count = 0; + while (count < maxdepth) { + count++; + DbgTrace(L"dbghelp32.dll %i: StackWalk64\n", GetCurrentThreadId()); + if (!StackWalk64(architecture, g_currentProcess, g_currentThread, &frame, ¤tContext, NULL, + SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { + // Couldn't trace back through any more frames. + break; + } + if (frame.AddrFrame.Offset == 0) { + // End of stack. + break; + } + + // Push this frame's program counter onto the CallStack. + push_back((UINT_PTR)frame.AddrPC.Offset); + } } diff --git a/criticalsection.h b/criticalsection.h index 53c4f775..3cf3c0eb 100644 --- a/criticalsection.h +++ b/criticalsection.h @@ -62,7 +62,6 @@ class CriticalSectionLocker { LeaveLock(); } - private: void LeaveLock() diff --git a/setup/version.h b/setup/version.h index 5822885f..8a1a2a01 100644 --- a/setup/version.h +++ b/setup/version.h @@ -1,9 +1,9 @@ -#define VLDVERSION L"2.2.1" -#define VERSION_NUMBER 2,2,1,0 -#define VERSION_STRING "2.2.1.0" +#define VLDVERSION L"2.2.2" +#define VERSION_NUMBER 2,2,2,0 +#define VERSION_STRING "2.2.2.0" #define VERSION_COPYRIGHT "Copyright (C) 2005-2011" #ifndef __FILE__ -!define VLD_VERSION "2.2.1" // NSIS Script +!define VLD_VERSION "2.2.2" // NSIS Script #endif diff --git a/utility.cpp b/utility.cpp index 1e4cce18..b2a29790 100644 --- a/utility.cpp +++ b/utility.cpp @@ -269,6 +269,7 @@ BOOL FindImport (HMODULE importmodule, HMODULE exportmodule, LPCSTR exportmodule IMAGE_THUNK_DATA *iate; FARPROC import; + DbgTrace(L"dbghelp32.dll %i: FindImport - ImageDirectoryEntryToDataEx\n", GetCurrentThreadId()); idte = FindOriginalImportDescriptor(importmodule, exportmodulename); if (idte == NULL) return FALSE; @@ -553,6 +554,7 @@ BOOL PatchModule (HMODULE importmodule, moduleentry_t patchtable [], UINT tables // Loop through the import patch table, individually patching each import // listed in the table. + DbgTrace(L"dbghelp32.dll %i: PatchModule - ImageDirectoryEntryToDataEx\n", GetCurrentThreadId()); for (index = 0; index < tablesize; index++) { entry = &patchtable[index]; if (PatchImport(importmodule, entry) == TRUE) { @@ -800,6 +802,7 @@ VOID RestoreModule (HMODULE importmodule, moduleentry_t patchtable [], UINT tabl // Loop through the import patch table, individually restoring each import // listed in the table. + DbgTrace(L"dbghelp32.dll %i: RestoreModule - ImageDirectoryEntryToDataEx\n", GetCurrentThreadId()); for (index = 0; index < tablesize; index++) { entry = &patchtable[index]; RestoreImport(importmodule, entry); diff --git a/utility.h b/utility.h index a58fc791..bb15d6fe 100644 --- a/utility.h +++ b/utility.h @@ -124,6 +124,15 @@ BOOL PatchImport (HMODULE importmodule, moduleentry_t *module); BOOL PatchModule (HMODULE importmodule, moduleentry_t patchtable [], UINT tablesize); VOID Print (LPWSTR message); VOID Report (LPCWSTR format, ...); +#ifdef _DEBUG +#define DbgPrint(x) Print(x) +#define DbgReport(...) Report(__VA_ARGS__) +#define DbgTrace(...) +#else +#define DbgPrint(x) +#define DbgReport(...) +#define DbgTrace(...) +#endif VOID RestoreImport (HMODULE importmodule, moduleentry_t* module); VOID RestoreModule (HMODULE importmodule, moduleentry_t patchtable [], UINT tablesize); VOID SetReportEncoding (encoding_e encoding); diff --git a/vld.cpp b/vld.cpp index 166d2a3e..33344f9f 100644 --- a/vld.cpp +++ b/vld.cpp @@ -54,6 +54,7 @@ HANDLE g_processHeap; // Handle to the process's heap (COM allocati CriticalSection g_stackWalkLock; // Serializes calls to StackWalk64 from the Debug Help Library. CriticalSection g_symbolLock; // Serializes calls to the Debug Help Library symbols handling APIs. ReportHookSet* g_pReportHooks; +volatile long g_loaderLockCounter = 0; // The one and only VisualLeakDetector object instance. __declspec(dllexport) VisualLeakDetector g_vld; @@ -209,6 +210,7 @@ VisualLeakDetector::VisualLeakDetector () #else SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); #endif + DbgTrace(L"dbghelp32.dll %i: SymInitializeW\n", GetCurrentThreadId()); if (!SymInitializeW(g_currentProcess, symbolpath, FALSE)) { Report(L"WARNING: Visual Leak Detector: The symbol handler failed to initialize (error=%lu).\n" L" File and function names will probably not be available in call stacks.\n", GetLastError()); @@ -223,6 +225,7 @@ VisualLeakDetector::VisualLeakDetector () // Attach Visual Leak Detector to every module loaded in the process. ModuleSet* newmodules = new ModuleSet(); newmodules->reserve(MODULE_SET_RESERVE); + DbgTrace(L"dbghelp32.dll %i: EnumerateLoadedModulesW64\n", GetCurrentThreadId()); EnumerateLoadedModulesW64(g_currentProcess, addLoadedModule, newmodules); attachToLoadedModules(newmodules); m_loadedModules = newmodules; @@ -347,6 +350,7 @@ VisualLeakDetector::~VisualLeakDetector () if (m_status & VLD_STATUS_INSTALLED) { // Detach Visual Leak Detector from all previously attached modules. + DbgTrace(L"dbghelp32.dll %i: EnumerateLoadedModulesW64\n", GetCurrentThreadId()); EnumerateLoadedModulesW64(g_currentProcess, detachFromModule, NULL); HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll"); @@ -379,6 +383,7 @@ VisualLeakDetector::~VisualLeakDetector () } // Free resources used by the symbol handler. + DbgTrace(L"dbghelp32.dll %i: SymCleanup\n", GetCurrentThreadId()); if (!SymCleanup(g_currentProcess)) { Report(L"WARNING: Visual Leak Detector: The symbol handler failed to deallocate resources (error=%lu).\n", GetLastError()); @@ -520,6 +525,7 @@ VOID VisualLeakDetector::attachToLoadedModules (ModuleSet *newmodules) g_symbolLock.Enter(); if ((refresh == true) && (moduleflags & VLD_MODULE_SYMBOLSLOADED)) { // Discard the previously loaded symbols, so we can refresh them. + DbgTrace(L"dbghelp32.dll %i: SymUnloadModule64\n", GetCurrentThreadId()); if (SymUnloadModule64(g_currentProcess, modulebase) == false) { Report(L"WARNING: Visual Leak Detector: Failed to unload the symbols for %s. Function names and line" L" numbers shown in the memory leak report for %s may be inaccurate.\n", modulename, modulename); @@ -539,9 +545,13 @@ VOID VisualLeakDetector::attachToLoadedModules (ModuleSet *newmodules) { CriticalSectionLocker cs(g_vld.m_heapMapLock); // fix GetModuleFileName thread lock g_symbolLock.Enter(); + DbgTrace(L"dbghelp32.dll %i: SymLoadModuleEx\n", GetCurrentThreadId()); DWORD64 module = SymLoadModuleEx(g_currentProcess, NULL, modulepath, NULL, modulebase, modulesize, NULL, 0); if (module == modulebase) + { + DbgTrace(L"dbghelp32.dll %i: SymGetModuleInfoW64\n", GetCurrentThreadId()); SymbolsLoaded = SymGetModuleInfoW64(g_currentProcess, modulebase, &moduleimageinfo); + } g_symbolLock.Leave(); } if (SymbolsLoaded) @@ -750,6 +760,7 @@ VOID VisualLeakDetector::configure () wcsncpy_s(inipath, MAX_PATH, L"vld.ini", _TRUNCATE); } } + DbgReport(L"Visual Leak Detector read settings from file: %s\n", inipath); #define BSIZE 64 WCHAR buffer [BSIZE] = {0}; @@ -1769,35 +1780,13 @@ FARPROC VisualLeakDetector::_RGetProcAddress (HMODULE module, LPCSTR procname) NTSTATUS VisualLeakDetector::_LdrLoadDll (LPWSTR searchpath, ULONG flags, unicodestring_t *modulename, PHANDLE modulehandle) { - CriticalSectionLocker cs(g_vld.m_loaderLock); - // Load the DLL. + _InterlockedIncrement(&g_loaderLockCounter); NTSTATUS status = LdrLoadDll(searchpath, flags, modulename, modulehandle); - if (STATUS_SUCCESS == status) { - // Duplicate code here from VisualLeakDetector::RefreshModules. Consider refactoring this out. - // Create a new set of all loaded modules, including any newly loaded - // modules. - ModuleSet *newmodules = new ModuleSet; - newmodules->reserve(MODULE_SET_RESERVE); - EnumerateLoadedModulesW64(g_currentProcess, addLoadedModule, newmodules); - - // Attach to all modules included in the set. - g_vld.attachToLoadedModules(newmodules); - - // Start using the new set of loaded modules. - g_vld.m_modulesLock.Enter(); - ModuleSet *oldmodules = g_vld.m_loadedModules; - g_vld.m_loadedModules = newmodules; - g_vld.m_modulesLock.Leave(); - - // Free resources used by the old module list. - for (ModuleSet::Iterator moduleit = oldmodules->begin(); moduleit != oldmodules->end(); ++moduleit) { - delete [] (*moduleit).name; - delete [] (*moduleit).path; - } - delete oldmodules; - } + if (STATUS_SUCCESS == status && g_loaderLockCounter == 1) + g_vld.RefreshModules(); + _InterlockedDecrement(&g_loaderLockCounter); return status; } @@ -1813,6 +1802,7 @@ VOID VisualLeakDetector::RefreshModules() // modules. ModuleSet* newmodules = new ModuleSet(); newmodules->reserve(MODULE_SET_RESERVE); + DbgTrace(L"dbghelp32.dll %i: EnumerateLoadedModulesW64\n", GetCurrentThreadId()); EnumerateLoadedModulesW64(g_currentProcess, addLoadedModule, newmodules); // Attach to all modules included in the set. @@ -1849,7 +1839,6 @@ void VisualLeakDetector::getCallStack( CallStack **&ppcallstack, context_t &cont // Find the information for the module that initiated this reallocation. bool VisualLeakDetector::isModuleExcluded(UINT_PTR address) { - bool excluded = false; moduleinfo_t moduleinfo; ModuleSet::Iterator moduleit; moduleinfo.addrLow = address; @@ -1858,10 +1847,11 @@ bool VisualLeakDetector::isModuleExcluded(UINT_PTR address) CriticalSectionLocker cs(g_vld.m_modulesLock); moduleit = g_vld.m_loadedModules->find(moduleinfo); - if (moduleit != g_vld.m_loadedModules->end()) { - excluded = (*moduleit).flags & VLD_MODULE_EXCLUDED ? true : false; - } - return excluded; + if (moduleit != g_vld.m_loadedModules->end()) + return (*moduleit).flags & VLD_MODULE_EXCLUDED ? true : false; + else if (g_loaderLockCounter != 0) // new module inside LdrLoadDll + return true; + return false; } SIZE_T VisualLeakDetector::GetLeaksCount() diff --git a/vld_hooks.cpp b/vld_hooks.cpp index 1a80f311..d65cf942 100644 --- a/vld_hooks.cpp +++ b/vld_hooks.cpp @@ -42,15 +42,15 @@ extern CriticalSection g_symbolLock; void VisualLeakDetector::firstAllocCall(tls_t * tls) { - if (tls->ppCallStack) - { - tls->flags &= ~VLD_TLS_CRTALLOC; - getCallStack(tls->ppCallStack, tls->context); - } - - // Reset thread local flags and variables for the next allocation. - tls->context.fp = 0x0; - tls->flags &= ~VLD_TLS_CRTALLOC; + if (tls->ppCallStack) + { + tls->flags &= ~VLD_TLS_CRTALLOC; + getCallStack(tls->ppCallStack, tls->context); + } + + // Reset thread local flags and variables for the next allocation. + tls->context.fp = 0x0; + tls->flags &= ~VLD_TLS_CRTALLOC; } //////////////////////////////////////////////////////////////////////////////// @@ -80,32 +80,32 @@ void VisualLeakDetector::firstAllocCall(tls_t * tls) // Returns the value returned from the specified calloc. // void* VisualLeakDetector::_calloc (calloc_t pcalloc, - context_t& context, - bool debugRuntime, - size_t num, - size_t size) + context_t& context, + bool debugRuntime, + size_t num, + size_t size) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // malloc is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // malloc is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - void* block = pcalloc(num, size); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + void* block = pcalloc(num, size); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // _malloc - This function is just a wrapper around the real malloc that sets @@ -124,27 +124,27 @@ void* VisualLeakDetector::_calloc (calloc_t pcalloc, // void *VisualLeakDetector::_malloc (malloc_t pmalloc, context_t& context, bool debugRuntime, size_t size) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // malloc is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // malloc is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - void* block = pmalloc(size); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + void* block = pmalloc(size); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // _new - This function is just a wrapper around the real CRT and MFC new @@ -163,27 +163,27 @@ void *VisualLeakDetector::_malloc (malloc_t pmalloc, context_t& context, bool de // void* VisualLeakDetector::_new (new_t pnew, context_t& context, bool debugRuntime, size_t size) { - tls_t* tls = g_vld.getTls(); + tls_t* tls = g_vld.getTls(); - // The new operator is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // The new operator is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - void* block = pnew(size); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + void* block = pnew(size); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // _realloc - This function is just a wrapper around the real realloc that sets @@ -203,32 +203,32 @@ void* VisualLeakDetector::_new (new_t pnew, context_t& context, bool debugRuntim // Returns the value returned from the specified realloc. // void* VisualLeakDetector::_realloc (realloc_t prealloc, - context_t& context, - bool debugRuntime, - void *mem, - size_t size) + context_t& context, + bool debugRuntime, + void *mem, + size_t size) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // realloc is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // realloc is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - void* block = prealloc(mem, size); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + void* block = prealloc(mem, size); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // _recalloc - This function is just a wrapper around the real _recalloc that sets @@ -248,83 +248,83 @@ void* VisualLeakDetector::_realloc (realloc_t prealloc, // Returns the value returned from the specified realloc. // void* VisualLeakDetector::__recalloc (_recalloc_t precalloc, - context_t& context, - bool debugRuntime, - void *mem, - size_t num, - size_t size) + context_t& context, + bool debugRuntime, + void *mem, + size_t num, + size_t size) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // realloc is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // realloc is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - void* block = precalloc(mem, num, size); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + void* block = precalloc(mem, num, size); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } char* VisualLeakDetector::__strdup( _strdup_t pstrdup, context_t& context, bool debugRuntime, const char* src ) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // realloc is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // realloc is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - char* block = pstrdup(src); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + char* block = pstrdup(src); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } wchar_t* VisualLeakDetector::__wcsdup( _wcsdup_t pwcsdup, context_t& context, bool debugRuntime, const wchar_t* src ) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // realloc is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // realloc is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - wchar_t* block = pwcsdup(src); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + wchar_t* block = pwcsdup(src); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // __aligned_malloc - This function is just a wrapper around the real malloc that sets @@ -342,29 +342,29 @@ wchar_t* VisualLeakDetector::__wcsdup( _wcsdup_t pwcsdup, context_t& context, bo // Returns the value returned from the specified malloc. // void *VisualLeakDetector::__aligned_malloc (_aligned_malloc_t pmalloc, context_t& context, bool debugRuntime, - size_t size, size_t alignment) + size_t size, size_t alignment) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // malloc is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // malloc is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - void* block = pmalloc(size, alignment); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + void* block = pmalloc(size, alignment); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // __aligned_offset_malloc - This function is just a wrapper around the real malloc that sets @@ -382,29 +382,29 @@ void *VisualLeakDetector::__aligned_malloc (_aligned_malloc_t pmalloc, context_t // Returns the value returned from the specified _aligned_offset_malloc. // void *VisualLeakDetector::__aligned_offset_malloc (_aligned_offset_malloc_t pmalloc, context_t& context, bool debugRuntime, - size_t size, size_t alignment, size_t offset) + size_t size, size_t alignment, size_t offset) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // malloc is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // malloc is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - void* block = pmalloc(size, alignment, offset); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + void* block = pmalloc(size, alignment, offset); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // __aligned_realloc - This function is just a wrapper around the real realloc that sets @@ -424,33 +424,33 @@ void *VisualLeakDetector::__aligned_offset_malloc (_aligned_offset_malloc_t pmal // Returns the value returned from the specified _aligned_realloc. // void* VisualLeakDetector::__aligned_realloc (_aligned_realloc_t prealloc, - context_t& context, - bool debugRuntime, - void *mem, - size_t size, - size_t alignment) + context_t& context, + bool debugRuntime, + void *mem, + size_t size, + size_t alignment) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // realloc is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // realloc is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - void* block = prealloc(mem, size, alignment); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + void* block = prealloc(mem, size, alignment); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // __aligned_offset_realloc - This function is just a wrapper around the real realloc that sets @@ -470,34 +470,34 @@ void* VisualLeakDetector::__aligned_realloc (_aligned_realloc_t prealloc, // Returns the value returned from the specified _aligned_offset_realloc. // void* VisualLeakDetector::__aligned_offset_realloc (_aligned_offset_realloc_t prealloc, - context_t& context, - bool debugRuntime, - void *mem, - size_t size, - size_t alignment, - size_t offset) + context_t& context, + bool debugRuntime, + void *mem, + size_t size, + size_t alignment, + size_t offset) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // realloc is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // realloc is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - void* block = prealloc(mem, size, alignment, offset); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + void* block = prealloc(mem, size, alignment, offset); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // __aligned_recalloc - This function is just a wrapper around the real recalloc that sets @@ -519,34 +519,34 @@ void* VisualLeakDetector::__aligned_offset_realloc (_aligned_offset_realloc_t p // Returns the value returned from the specified _aligned_realloc. // void* VisualLeakDetector::__aligned_recalloc (_aligned_recalloc_t precalloc, - context_t& context, - bool debugRuntime, - void *mem, - size_t num, - size_t size, - size_t alignment) + context_t& context, + bool debugRuntime, + void *mem, + size_t num, + size_t size, + size_t alignment) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // realloc is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // realloc is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - void* block = precalloc(mem, num, size, alignment); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + void* block = precalloc(mem, num, size, alignment); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // __aligned_offset_recalloc - This function is just a wrapper around the real recalloc that sets @@ -568,35 +568,35 @@ void* VisualLeakDetector::__aligned_recalloc (_aligned_recalloc_t precalloc, // Returns the value returned from the specified _aligned_offset_realloc. // void* VisualLeakDetector::__aligned_offset_recalloc (_aligned_offset_recalloc_t precalloc, - context_t& context, - bool debugRuntime, - void *mem, - size_t num, - size_t size, - size_t alignment, - size_t offset) + context_t& context, + bool debugRuntime, + void *mem, + size_t num, + size_t size, + size_t alignment, + size_t offset) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // realloc is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // realloc is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - void* block = precalloc(mem, num, size, alignment, offset); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + void* block = precalloc(mem, num, size, alignment, offset); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // __aligned_malloc_dbg - This function is just a wrapper around the real _aligned_malloc_dbg @@ -622,35 +622,35 @@ void* VisualLeakDetector::__aligned_offset_recalloc (_aligned_offset_recalloc_t // Returns the value returned by the specified _aligned_malloc_dbg. // void* VisualLeakDetector::__aligned_malloc_dbg (_aligned_malloc_dbg_t p_malloc_dbg, - context_t& context, - bool debugRuntime, - size_t size, - size_t alignment, - int type, - char const *file, - int line) + context_t& context, + bool debugRuntime, + size_t size, + size_t alignment, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // _malloc_dbg is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // _malloc_dbg is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - void* block = p_malloc_dbg(size, alignment, type, file, line); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + void* block = p_malloc_dbg(size, alignment, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // __aligned_offset_malloc_dbg - This function is just a wrapper around the real @@ -676,36 +676,36 @@ void* VisualLeakDetector::__aligned_malloc_dbg (_aligned_malloc_dbg_t p_malloc_ // Returns the value returned by the specified _aligned_malloc_dbg. // void* VisualLeakDetector::__aligned_offset_malloc_dbg (_aligned_offset_malloc_dbg_t p_malloc_dbg, - context_t& context, - bool debugRuntime, - size_t size, - size_t alignment, - size_t offset, - int type, - char const *file, - int line) + context_t& context, + bool debugRuntime, + size_t size, + size_t alignment, + size_t offset, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // _malloc_dbg is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // _malloc_dbg is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - void* block = p_malloc_dbg(size, alignment, offset, type, file, line); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + void* block = p_malloc_dbg(size, alignment, offset, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // _aligned_realloc_debug - This function is just a wrapper around the real @@ -733,36 +733,36 @@ void* VisualLeakDetector::__aligned_offset_malloc_dbg (_aligned_offset_malloc_db // Returns the value returned by the specified _realloc_dbg. // void* VisualLeakDetector::__aligned_realloc_dbg (_aligned_realloc_dbg_t p_realloc_dbg, - context_t& context, - bool debugRuntime, - void *mem, - size_t size, - size_t alignment, - int type, - char const *file, - int line) + context_t& context, + bool debugRuntime, + void *mem, + size_t size, + size_t alignment, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // _realloc_dbg is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // _realloc_dbg is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - void* block = p_realloc_dbg(mem, size, alignment, type, file, line); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + void* block = p_realloc_dbg(mem, size, alignment, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // _aligned_offset_realloc_debug - This function is just a wrapper around the real @@ -790,37 +790,37 @@ void* VisualLeakDetector::__aligned_realloc_dbg (_aligned_realloc_dbg_t p_reall // Returns the value returned by the specified _realloc_dbg. // void* VisualLeakDetector::__aligned_offset_realloc_dbg (_aligned_offset_realloc_dbg_t p_realloc_dbg, - context_t& context, - bool debugRuntime, - void *mem, - size_t size, - size_t alignment, - size_t offset, - int type, - char const *file, - int line) + context_t& context, + bool debugRuntime, + void *mem, + size_t size, + size_t alignment, + size_t offset, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // _realloc_dbg is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // _realloc_dbg is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - void* block = p_realloc_dbg(mem, size, alignment, offset, type, file, line); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + void* block = p_realloc_dbg(mem, size, alignment, offset, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // _aligned_recalloc_debug - This function is just a wrapper around the real @@ -850,37 +850,37 @@ void* VisualLeakDetector::__aligned_offset_realloc_dbg (_aligned_offset_realloc_ // Returns the value returned by the specified _realloc_dbg. // void* VisualLeakDetector::__aligned_recalloc_dbg (_aligned_recalloc_dbg_t p_recalloc_dbg, - context_t& context, - bool debugRuntime, - void *mem, - size_t num, - size_t size, - size_t alignment, - int type, - char const *file, - int line) + context_t& context, + bool debugRuntime, + void *mem, + size_t num, + size_t size, + size_t alignment, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // _realloc_dbg is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // _realloc_dbg is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - void* block = p_recalloc_dbg(mem, num, size, alignment, type, file, line); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + void* block = p_recalloc_dbg(mem, num, size, alignment, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // _aligned_offset_recalloc_debug - This function is just a wrapper around the real @@ -910,38 +910,38 @@ void* VisualLeakDetector::__aligned_recalloc_dbg (_aligned_recalloc_dbg_t p_rec // Returns the value returned by the specified _realloc_dbg. // void* VisualLeakDetector::__aligned_offset_recalloc_dbg (_aligned_offset_recalloc_dbg_t p_recalloc_dbg, - context_t& context, - bool debugRuntime, - void *mem, - size_t num, - size_t size, - size_t alignment, - size_t offset, - int type, - char const *file, - int line) + context_t& context, + bool debugRuntime, + void *mem, + size_t num, + size_t size, + size_t alignment, + size_t offset, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // _realloc_dbg is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // _realloc_dbg is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - void* block = p_recalloc_dbg(mem, num, size, alignment, offset, type, file, line); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + void* block = p_recalloc_dbg(mem, num, size, alignment, offset, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } //////////////////////////////////////////////////////////////////////////////// @@ -977,35 +977,35 @@ void* VisualLeakDetector::__aligned_offset_recalloc_dbg (_aligned_offset_recallo // Returns the value returned by the specified _calloc_dbg. // void* VisualLeakDetector::__calloc_dbg (_calloc_dbg_t p_calloc_dbg, - context_t& context, - bool debugRuntime, - size_t num, - size_t size, - int type, - char const *file, - int line) + context_t& context, + bool debugRuntime, + size_t num, + size_t size, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // _malloc_dbg is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // _malloc_dbg is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - void* block = p_calloc_dbg(num, size, type, file, line); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + void* block = p_calloc_dbg(num, size, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // __malloc_dbg - This function is just a wrapper around the real _malloc_dbg @@ -1031,96 +1031,96 @@ void* VisualLeakDetector::__calloc_dbg (_calloc_dbg_t p_calloc_dbg, // Returns the value returned by the specified _malloc_dbg. // void* VisualLeakDetector::__malloc_dbg (_malloc_dbg_t p_malloc_dbg, - context_t& context, - bool debugRuntime, - size_t size, - int type, - char const *file, - int line) + context_t& context, + bool debugRuntime, + size_t size, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // _malloc_dbg is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // _malloc_dbg is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - void* block = p_malloc_dbg(size, type, file, line); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + void* block = p_malloc_dbg(size, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } char* VisualLeakDetector::__strdup_dbg (_strdup_dbg_t p_strdup_dbg, - context_t& context, - bool debugRuntime, - const char* src, - int type, - char const *file, - int line) + context_t& context, + bool debugRuntime, + const char* src, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // _malloc_dbg is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // _malloc_dbg is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - char* block = p_strdup_dbg(src, type, file, line); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + char* block = p_strdup_dbg(src, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } wchar_t* VisualLeakDetector::__wcsdup_dbg (_wcsdup_dbg_t p_wcsdup_dbg, - context_t& context, - bool debugRuntime, - const wchar_t* src, - int type, - char const *file, - int line) + context_t& context, + bool debugRuntime, + const wchar_t* src, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // _malloc_dbg is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // _malloc_dbg is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - wchar_t* block = p_wcsdup_dbg(src, type, file, line); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + wchar_t* block = p_wcsdup_dbg(src, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // new_dbg_crt - This function is just a wrapper around the real CRT debug new @@ -1146,34 +1146,34 @@ wchar_t* VisualLeakDetector::__wcsdup_dbg (_wcsdup_dbg_t p_wcsdup_dbg, // Returns the value returned by the specified CRT debug new operator. // void* VisualLeakDetector::__new_dbg_crt (new_dbg_crt_t pnew_dbg_crt, - context_t& context, - bool debugRuntime, - size_t size, - int type, - char const *file, - int line) + context_t& context, + bool debugRuntime, + size_t size, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // The debug new operator is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // The debug new operator is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - void* block = pnew_dbg_crt(size, type, file, line); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + void* block = pnew_dbg_crt(size, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // new_dbg_mfc - This function is just a wrapper around the real MFC debug new @@ -1199,29 +1199,29 @@ void* VisualLeakDetector::__new_dbg_crt (new_dbg_crt_t pnew_dbg_crt, // Returns the value returned by the specified CRT debug new operator. // void* VisualLeakDetector::__new_dbg_mfc (new_dbg_crt_t pnew_dbg, - context_t& context, - size_t size, - int type, - char const *file, - int line) + context_t& context, + size_t size, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - void* block = pnew_dbg(size, type, file, line); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + void* block = pnew_dbg(size, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // new_dbg_mfc - This function is just a wrapper around the real MFC debug new @@ -1245,28 +1245,28 @@ void* VisualLeakDetector::__new_dbg_mfc (new_dbg_crt_t pnew_dbg, // Returns the value returned by the specified MFC debug new operator. // void* VisualLeakDetector::__new_dbg_mfc (new_dbg_mfc_t pnew_dbg_mfc, - context_t& context, - size_t size, - char const *file, - int line) + context_t& context, + size_t size, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - void* block = pnew_dbg_mfc(size, file, line); + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + void* block = pnew_dbg_mfc(size, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // __realloc_debug - This function is just a wrapper around the real @@ -1294,35 +1294,35 @@ void* VisualLeakDetector::__new_dbg_mfc (new_dbg_mfc_t pnew_dbg_mfc, // Returns the value returned by the specified _realloc_dbg. // void* VisualLeakDetector::__realloc_dbg (_realloc_dbg_t p_realloc_dbg, - context_t& context, - bool debugRuntime, - void *mem, - size_t size, - int type, - char const *file, - int line) + context_t& context, + bool debugRuntime, + void *mem, + size_t size, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // _realloc_dbg is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // _realloc_dbg is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - void* block = p_realloc_dbg(mem, size, type, file, line); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + void* block = p_realloc_dbg(mem, size, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // __recalloc_debug - This function is just a wrapper around the real @@ -1350,36 +1350,36 @@ void* VisualLeakDetector::__realloc_dbg (_realloc_dbg_t p_realloc_dbg, // Returns the value returned by the specified _realloc_dbg. // void* VisualLeakDetector::__recalloc_dbg (_recalloc_dbg_t p_recalloc_dbg, - context_t& context, - bool debugRuntime, - void *mem, - size_t num, - size_t size, - int type, - char const *file, - int line) + context_t& context, + bool debugRuntime, + void *mem, + size_t num, + size_t size, + int type, + char const *file, + int line) { - tls_t *tls = g_vld.getTls(); + tls_t *tls = g_vld.getTls(); - // _realloc_dbg is a CRT function and allocates from the CRT heap. - if (debugRuntime) - tls->flags |= VLD_TLS_CRTALLOC; + // _realloc_dbg is a CRT function and allocates from the CRT heap. + if (debugRuntime) + tls->flags |= VLD_TLS_CRTALLOC; - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - tls->context = context; - tls->blockProcessed = FALSE; - } + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + tls->context = context; + tls->blockProcessed = FALSE; + } - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - void* block = p_recalloc_dbg(mem, num, size, type, file, line); + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + void* block = p_recalloc_dbg(mem, num, size, type, file, line); - if (firstcall) - firstAllocCall(tls); + if (firstcall) + firstAllocCall(tls); - return block; + return block; } // _HeapCreate - Calls to HeapCreate are patched through to this function. This @@ -1398,58 +1398,59 @@ void* VisualLeakDetector::__recalloc_dbg (_recalloc_dbg_t p_recalloc_dbg, // HANDLE VisualLeakDetector::_HeapCreate (DWORD options, SIZE_T initsize, SIZE_T maxsize) { - // Get the return address within the calling function. - UINT_PTR ra = (UINT_PTR)_ReturnAddress(); - - // Create the heap. - HANDLE heap = HeapCreate(options, initsize, maxsize); - - // Map the created heap handle to a new block map. - g_vld.mapHeap(heap); - - // Try to get the name of the function containing the return address. - BYTE symbolbuffer [sizeof(SYMBOL_INFO) + MAX_SYMBOL_NAME_SIZE] = { 0 }; - SYMBOL_INFO *functioninfo = (SYMBOL_INFO*)&symbolbuffer; - functioninfo->SizeOfStruct = sizeof(SYMBOL_INFO); - functioninfo->MaxNameLen = MAX_SYMBOL_NAME_LENGTH; - - g_symbolLock.Enter(); - DWORD64 displacement; - BOOL symfound = SymFromAddrW(g_currentProcess, ra, &displacement, functioninfo); - g_symbolLock.Leave(); - if (symfound == TRUE) { - if (wcscmp(L"_heap_init", functioninfo->Name) == 0) { - // HeapCreate was called by _heap_init. This is a static CRT heap (msvcr*.dll). - CriticalSectionLocker cs(g_vld.m_heapMapLock); - HeapMap::Iterator heapit = g_vld.m_heapMap->find(heap); - assert(heapit != g_vld.m_heapMap->end()); - HMODULE hCallingModule = (HMODULE)functioninfo->ModBase; - if (hCallingModule) - { - HMODULE hCurrentModule = GetModuleHandleW(NULL); - if (hCallingModule == hCurrentModule) - { - // CRT static linking + // Get the return address within the calling function. + UINT_PTR ra = (UINT_PTR)_ReturnAddress(); + + // Create the heap. + HANDLE heap = HeapCreate(options, initsize, maxsize); + + // Map the created heap handle to a new block map. + g_vld.mapHeap(heap); + + // Try to get the name of the function containing the return address. + BYTE symbolbuffer [sizeof(SYMBOL_INFO) + MAX_SYMBOL_NAME_SIZE] = { 0 }; + SYMBOL_INFO *functioninfo = (SYMBOL_INFO*)&symbolbuffer; + functioninfo->SizeOfStruct = sizeof(SYMBOL_INFO); + functioninfo->MaxNameLen = MAX_SYMBOL_NAME_LENGTH; + + g_symbolLock.Enter(); + DWORD64 displacement; + DbgTrace(L"dbghelp32.dll %i: SymFromAddrW\n", GetCurrentThreadId()); + BOOL symfound = SymFromAddrW(g_currentProcess, ra, &displacement, functioninfo); + g_symbolLock.Leave(); + if (symfound == TRUE) { + if (wcscmp(L"_heap_init", functioninfo->Name) == 0) { + // HeapCreate was called by _heap_init. This is a static CRT heap (msvcr*.dll). + CriticalSectionLocker cs(g_vld.m_heapMapLock); + HeapMap::Iterator heapit = g_vld.m_heapMap->find(heap); + assert(heapit != g_vld.m_heapMap->end()); + HMODULE hCallingModule = (HMODULE)functioninfo->ModBase; + if (hCallingModule) + { + HMODULE hCurrentModule = GetModuleHandleW(NULL); + if (hCallingModule == hCurrentModule) + { + // CRT static linking #ifdef _DEBUG // debug runtime - (*heapit).second->flags |= VLD_HEAP_CRT_DBG; + (*heapit).second->flags |= VLD_HEAP_CRT_DBG; #endif - } - else - { - // CRT dynamic linking - WCHAR callingmodulename [MAX_PATH] = L""; - if (GetModuleFileName(hCallingModule, callingmodulename, _countof(callingmodulename)) > 0) - { - _wcslwr_s(callingmodulename); - if (wcsstr(callingmodulename, L"d.dll") != 0) // debug runtime - (*heapit).second->flags |= VLD_HEAP_CRT_DBG; - } - } - } - } - } - - return heap; + } + else + { + // CRT dynamic linking + WCHAR callingmodulename [MAX_PATH] = L""; + if (GetModuleFileName(hCallingModule, callingmodulename, _countof(callingmodulename)) > 0) + { + _wcslwr_s(callingmodulename); + if (wcsstr(callingmodulename, L"d.dll") != 0) // debug runtime + (*heapit).second->flags |= VLD_HEAP_CRT_DBG; + } + } + } + } + } + + return heap; } // _HeapDestroy - Calls to HeapDestroy are patched through to this function. @@ -1464,16 +1465,16 @@ HANDLE VisualLeakDetector::_HeapCreate (DWORD options, SIZE_T initsize, SIZE_T m // BOOL VisualLeakDetector::_HeapDestroy (HANDLE heap) { - // After this heap is destroyed, the heap's address space will be unmapped - // from the process's address space. So, we'd better generate a leak report - // for this heap now, while we can still read from the memory blocks - // allocated to it. - if (!(g_vld.m_options & VLD_OPT_SKIP_HEAPFREE_LEAKS)) - g_vld.reportHeapLeaks(heap); + // After this heap is destroyed, the heap's address space will be unmapped + // from the process's address space. So, we'd better generate a leak report + // for this heap now, while we can still read from the memory blocks + // allocated to it. + if (!(g_vld.m_options & VLD_OPT_SKIP_HEAPFREE_LEAKS)) + g_vld.reportHeapLeaks(heap); - g_vld.unmapHeap(heap); + g_vld.unmapHeap(heap); - return HeapDestroy(heap); + return HeapDestroy(heap); } // _RtlAllocateHeap - Calls to RtlAllocateHeap are patched through to this @@ -1494,92 +1495,92 @@ BOOL VisualLeakDetector::_HeapDestroy (HANDLE heap) // LPVOID VisualLeakDetector::_RtlAllocateHeap (HANDLE heap, DWORD flags, SIZE_T size) { - // Allocate the block. - LPVOID block = RtlAllocateHeap(heap, flags, size); - - if ((block == NULL) || !g_vld.enabled()) - return block; - - tls_t* tls = g_vld.getTls(); - tls->blockProcessed = TRUE; - bool firstcall = (tls->context.fp == 0x0); - context_t context; - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - CAPTURE_CONTEXT(context); - } - else - context = tls->context; - - if (isModuleExcluded(GET_RETURN_ADDRESS(context))) - return block; - - if (!firstcall && (g_vld.m_options & VLD_OPT_TRACE_INTERNAL_FRAMES)) { - // Begin the stack trace with the current frame. Obtain the current - // frame pointer. - firstcall = true; - CAPTURE_CONTEXT(context); - } - - tls->context = context; - - AllocateHeap(tls, heap, block, size); - - if (firstcall) - firstAllocCall(tls); - - return block; + // Allocate the block. + LPVOID block = RtlAllocateHeap(heap, flags, size); + + if ((block == NULL) || !g_vld.enabled()) + return block; + + tls_t* tls = g_vld.getTls(); + tls->blockProcessed = TRUE; + bool firstcall = (tls->context.fp == 0x0); + context_t context; + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + CAPTURE_CONTEXT(context); + } + else + context = tls->context; + + if (isModuleExcluded(GET_RETURN_ADDRESS(context))) + return block; + + if (!firstcall && (g_vld.m_options & VLD_OPT_TRACE_INTERNAL_FRAMES)) { + // Begin the stack trace with the current frame. Obtain the current + // frame pointer. + firstcall = true; + CAPTURE_CONTEXT(context); + } + + tls->context = context; + + AllocateHeap(tls, heap, block, size); + + if (firstcall) + firstAllocCall(tls); + + return block; } // HeapAlloc (kernel32.dll) call RtlAllocateHeap (ntdll.dll) LPVOID VisualLeakDetector::_HeapAlloc (HANDLE heap, DWORD flags, SIZE_T size) { - // Allocate the block. - LPVOID block = HeapAlloc(heap, flags, size); - - if ((block == NULL) || !g_vld.enabled()) - return block; - - tls_t* tls = g_vld.getTls(); - tls->blockProcessed = TRUE; - bool firstcall = (tls->context.fp == 0x0); - context_t context; - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - CAPTURE_CONTEXT(context); - } - else - context = tls->context; - - if (isModuleExcluded(GET_RETURN_ADDRESS(context))) - return block; - - if (!firstcall && (g_vld.m_options & VLD_OPT_TRACE_INTERNAL_FRAMES)) { - // Begin the stack trace with the current frame. Obtain the current - // frame pointer. - firstcall = true; - CAPTURE_CONTEXT(context); - } - - tls->context = context; - - AllocateHeap(tls, heap, block, size); - - if (firstcall) - firstAllocCall(tls); - - return block; + // Allocate the block. + LPVOID block = HeapAlloc(heap, flags, size); + + if ((block == NULL) || !g_vld.enabled()) + return block; + + tls_t* tls = g_vld.getTls(); + tls->blockProcessed = TRUE; + bool firstcall = (tls->context.fp == 0x0); + context_t context; + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + CAPTURE_CONTEXT(context); + } + else + context = tls->context; + + if (isModuleExcluded(GET_RETURN_ADDRESS(context))) + return block; + + if (!firstcall && (g_vld.m_options & VLD_OPT_TRACE_INTERNAL_FRAMES)) { + // Begin the stack trace with the current frame. Obtain the current + // frame pointer. + firstcall = true; + CAPTURE_CONTEXT(context); + } + + tls->context = context; + + AllocateHeap(tls, heap, block, size); + + if (firstcall) + firstAllocCall(tls); + + return block; } void VisualLeakDetector::AllocateHeap (tls_t* tls, HANDLE heap, LPVOID block, SIZE_T size) { - bool crtalloc = (tls->flags & VLD_TLS_CRTALLOC) ? true : false; + bool crtalloc = (tls->flags & VLD_TLS_CRTALLOC) ? true : false; - // The module that initiated this allocation is included in leak - // detection. Map this block to the specified heap. - g_vld.mapBlock(heap, block, size, crtalloc, tls->ppCallStack); + // The module that initiated this allocation is included in leak + // detection. Map this block to the specified heap. + g_vld.mapBlock(heap, block, size, crtalloc, tls->ppCallStack); } // _RtlFreeHeap - Calls to RtlFreeHeap are patched through to this function. @@ -1599,41 +1600,41 @@ void VisualLeakDetector::AllocateHeap (tls_t* tls, HANDLE heap, LPVOID block, SI // BYTE VisualLeakDetector::_RtlFreeHeap (HANDLE heap, DWORD flags, LPVOID mem) { - BYTE status; + BYTE status; - if (!g_symbolLock.IsLockedByCurrentThread()) // skip dbghelp.dll calls - { - context_t context; - // Record the current frame pointer. - CAPTURE_CONTEXT(context); + if (!g_symbolLock.IsLockedByCurrentThread()) // skip dbghelp.dll calls + { + context_t context; + // Record the current frame pointer. + CAPTURE_CONTEXT(context); - // Unmap the block from the specified heap. - g_vld.unmapBlock(heap, mem, context); - } + // Unmap the block from the specified heap. + g_vld.unmapBlock(heap, mem, context); + } - status = RtlFreeHeap(heap, flags, mem); + status = RtlFreeHeap(heap, flags, mem); - return status; + return status; } // HeapFree (kernel32.dll) call RtlFreeHeap (ntdll.dll) BOOL VisualLeakDetector::_HeapFree (HANDLE heap, DWORD flags, LPVOID mem) { - BOOL status; + BOOL status; - if (!g_symbolLock.IsLockedByCurrentThread()) // skip dbghelp.dll calls - { - context_t context; - // Record the current frame pointer. - CAPTURE_CONTEXT(context); + if (!g_symbolLock.IsLockedByCurrentThread()) // skip dbghelp.dll calls + { + context_t context; + // Record the current frame pointer. + CAPTURE_CONTEXT(context); - // Unmap the block from the specified heap. - g_vld.unmapBlock(heap, mem, context); - } + // Unmap the block from the specified heap. + g_vld.unmapBlock(heap, mem, context); + } - status = HeapFree(heap, flags, mem); + status = HeapFree(heap, flags, mem); - return status; + return status; } // _RtlReAllocateHeap - Calls to RtlReAllocateHeap are patched through to this @@ -1658,110 +1659,110 @@ BOOL VisualLeakDetector::_HeapFree (HANDLE heap, DWORD flags, LPVOID mem) // LPVOID VisualLeakDetector::_RtlReAllocateHeap (HANDLE heap, DWORD flags, LPVOID mem, SIZE_T size) { - LPVOID newmem; - - // Reallocate the block. - newmem = RtlReAllocateHeap(heap, flags, mem, size); - if (newmem == NULL) - return newmem; - - tls_t *tls = g_vld.getTls(); - tls->blockProcessed = TRUE; - bool firstcall = (tls->context.fp == 0x0); - context_t context; - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - CAPTURE_CONTEXT(context); - } - else - context = tls->context; - - if (isModuleExcluded(GET_RETURN_ADDRESS(context))) - return newmem; - - if (!firstcall && (g_vld.m_options & VLD_OPT_TRACE_INTERNAL_FRAMES)) { - // Begin the stack trace with the current frame. Obtain the current - // frame pointer. - firstcall = true; - CAPTURE_CONTEXT(context); - } - - ReAllocateHeap(tls, heap, mem, newmem, size, context); - - if (firstcall) - { - firstAllocCall(tls); - tls->ppCallStack = NULL; - } - - return newmem; + LPVOID newmem; + + // Reallocate the block. + newmem = RtlReAllocateHeap(heap, flags, mem, size); + if (newmem == NULL) + return newmem; + + tls_t *tls = g_vld.getTls(); + tls->blockProcessed = TRUE; + bool firstcall = (tls->context.fp == 0x0); + context_t context; + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + CAPTURE_CONTEXT(context); + } + else + context = tls->context; + + if (isModuleExcluded(GET_RETURN_ADDRESS(context))) + return newmem; + + if (!firstcall && (g_vld.m_options & VLD_OPT_TRACE_INTERNAL_FRAMES)) { + // Begin the stack trace with the current frame. Obtain the current + // frame pointer. + firstcall = true; + CAPTURE_CONTEXT(context); + } + + ReAllocateHeap(tls, heap, mem, newmem, size, context); + + if (firstcall) + { + firstAllocCall(tls); + tls->ppCallStack = NULL; + } + + return newmem; } // for kernel32.dll LPVOID VisualLeakDetector::_HeapReAlloc (HANDLE heap, DWORD flags, LPVOID mem, SIZE_T size) { - LPVOID newmem; - - // Reallocate the block. - newmem = HeapReAlloc(heap, flags, mem, size); - if (newmem == NULL) - return newmem; - - tls_t *tls = g_vld.getTls(); - tls->blockProcessed = TRUE; - bool firstcall = (tls->context.fp == 0x0); - context_t context; - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - CAPTURE_CONTEXT(context); - } - else - context = tls->context; - - if (isModuleExcluded(GET_RETURN_ADDRESS(context))) - return newmem; - - if (!firstcall && (g_vld.m_options & VLD_OPT_TRACE_INTERNAL_FRAMES)) { - // Begin the stack trace with the current frame. Obtain the current - // frame pointer. - firstcall = true; - CAPTURE_CONTEXT(context); - } - - ReAllocateHeap(tls, heap, mem, newmem, size, context); - - if (firstcall) - { - firstAllocCall(tls); - tls->ppCallStack = NULL; - } - - return newmem; + LPVOID newmem; + + // Reallocate the block. + newmem = HeapReAlloc(heap, flags, mem, size); + if (newmem == NULL) + return newmem; + + tls_t *tls = g_vld.getTls(); + tls->blockProcessed = TRUE; + bool firstcall = (tls->context.fp == 0x0); + context_t context; + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + CAPTURE_CONTEXT(context); + } + else + context = tls->context; + + if (isModuleExcluded(GET_RETURN_ADDRESS(context))) + return newmem; + + if (!firstcall && (g_vld.m_options & VLD_OPT_TRACE_INTERNAL_FRAMES)) { + // Begin the stack trace with the current frame. Obtain the current + // frame pointer. + firstcall = true; + CAPTURE_CONTEXT(context); + } + + ReAllocateHeap(tls, heap, mem, newmem, size, context); + + if (firstcall) + { + firstAllocCall(tls); + tls->ppCallStack = NULL; + } + + return newmem; } void VisualLeakDetector::ReAllocateHeap (tls_t *tls, HANDLE heap, LPVOID mem, LPVOID newmem, SIZE_T size, const context_t &context) { - bool crtalloc = (tls->flags & VLD_TLS_CRTALLOC) ? true : false; + bool crtalloc = (tls->flags & VLD_TLS_CRTALLOC) ? true : false; - // Reset thread local flags and variables, in case any libraries called - // into while remapping the block allocate some memory. - tls->context.fp = 0x0; - tls->flags &= ~VLD_TLS_CRTALLOC; + // Reset thread local flags and variables, in case any libraries called + // into while remapping the block allocate some memory. + tls->context.fp = 0x0; + tls->flags &= ~VLD_TLS_CRTALLOC; - // The module that initiated this allocation is included in leak - // detection. Remap the block. - g_vld.remapBlock(heap, mem, newmem, size, crtalloc, tls->ppCallStack, context); + // The module that initiated this allocation is included in leak + // detection. Remap the block. + g_vld.remapBlock(heap, mem, newmem, size, crtalloc, tls->ppCallStack, context); #ifdef _DEBUG - if(tls->context.fp != 0) - __debugbreak(); + if(tls->context.fp != 0) + __debugbreak(); #endif - if (crtalloc) - tls->flags |= VLD_TLS_CRTALLOC; + if (crtalloc) + tls->flags |= VLD_TLS_CRTALLOC; - tls->context = context; + tls->context = context; } //////////////////////////////////////////////////////////////////////////////// @@ -1788,36 +1789,36 @@ void VisualLeakDetector::ReAllocateHeap (tls_t *tls, HANDLE heap, LPVOID mem, LP // HRESULT VisualLeakDetector::_CoGetMalloc (DWORD context, LPMALLOC *imalloc) { - static CoGetMalloc_t pCoGetMalloc = NULL; - - HRESULT hr = S_OK; - - HMODULE ole32; - - *imalloc = (LPMALLOC)&g_vld; - - if (pCoGetMalloc == NULL) { - // This is the first call to this function. Link to the real - // CoGetMalloc and get a pointer to the system implementation of the - // IMalloc interface. - ole32 = GetModuleHandleW(L"ole32.dll"); - pCoGetMalloc = (CoGetMalloc_t)g_vld._RGetProcAddress(ole32, "CoGetMalloc"); - hr = pCoGetMalloc(context, &g_vld.m_iMalloc); - } - else - { - // wait for different thread initialization - int c = 0; - while(g_vld.m_iMalloc == NULL && c < 10) - { - Sleep(1); - c++; - } - if (g_vld.m_iMalloc == NULL) - hr = E_INVALIDARG; - } - - return hr; + static CoGetMalloc_t pCoGetMalloc = NULL; + + HRESULT hr = S_OK; + + HMODULE ole32; + + *imalloc = (LPMALLOC)&g_vld; + + if (pCoGetMalloc == NULL) { + // This is the first call to this function. Link to the real + // CoGetMalloc and get a pointer to the system implementation of the + // IMalloc interface. + ole32 = GetModuleHandleW(L"ole32.dll"); + pCoGetMalloc = (CoGetMalloc_t)g_vld._RGetProcAddress(ole32, "CoGetMalloc"); + hr = pCoGetMalloc(context, &g_vld.m_iMalloc); + } + else + { + // wait for different thread initialization + int c = 0; + while(g_vld.m_iMalloc == NULL && c < 10) + { + Sleep(1); + c++; + } + if (g_vld.m_iMalloc == NULL) + hr = E_INVALIDARG; + } + + return hr; } // _CoTaskMemAlloc - Calls to CoTaskMemAlloc are patched through to this @@ -1833,36 +1834,36 @@ HRESULT VisualLeakDetector::_CoGetMalloc (DWORD context, LPMALLOC *imalloc) // LPVOID VisualLeakDetector::_CoTaskMemAlloc (SIZE_T size) { - static CoTaskMemAlloc_t pCoTaskMemAlloc = NULL; - - LPVOID block; - context_t context; - HMODULE ole32; - tls_t *tls = g_vld.getTls(); - - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - CAPTURE_CONTEXT(context); - tls->context = context; - 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); - - if (firstcall) - firstAllocCall(tls); - - return block; + static CoTaskMemAlloc_t pCoTaskMemAlloc = NULL; + + LPVOID block; + context_t context; + HMODULE ole32; + tls_t *tls = g_vld.getTls(); + + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + CAPTURE_CONTEXT(context); + tls->context = context; + 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); + + if (firstcall) + firstAllocCall(tls); + + return block; } // _CoTaskMemRealloc - Calls to CoTaskMemRealloc are patched through to this @@ -1880,36 +1881,36 @@ LPVOID VisualLeakDetector::_CoTaskMemAlloc (SIZE_T size) // LPVOID VisualLeakDetector::_CoTaskMemRealloc (LPVOID mem, SIZE_T size) { - static CoTaskMemRealloc_t pCoTaskMemRealloc = NULL; - - LPVOID block; - context_t context; - HMODULE ole32; - tls_t *tls = g_vld.getTls(); - - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - CAPTURE_CONTEXT(context); - tls->context = context; - 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); - - if (firstcall) - firstAllocCall(tls); - - return block; + static CoTaskMemRealloc_t pCoTaskMemRealloc = NULL; + + LPVOID block; + context_t context; + HMODULE ole32; + tls_t *tls = g_vld.getTls(); + + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + CAPTURE_CONTEXT(context); + tls->context = context; + 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); + + if (firstcall) + firstAllocCall(tls); + + return block; } //////////////////////////////////////////////////////////////////////////////// @@ -1928,8 +1929,8 @@ LPVOID VisualLeakDetector::_CoTaskMemRealloc (LPVOID mem, SIZE_T size) // ULONG VisualLeakDetector::AddRef () { - assert(m_iMalloc != NULL); - return (m_iMalloc) ? m_iMalloc->AddRef() : 0; + assert(m_iMalloc != NULL); + return (m_iMalloc) ? m_iMalloc->AddRef() : 0; } // Alloc - Calls to IMalloc::Alloc end up here. This function is just a wrapper @@ -1944,27 +1945,27 @@ ULONG VisualLeakDetector::AddRef () // LPVOID VisualLeakDetector::Alloc (SIZE_T size) { - LPVOID block; - context_t context; - tls_t *tls = getTls(); - - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - CAPTURE_CONTEXT(context); - tls->context = context; - tls->blockProcessed = FALSE; - } - - // Do the allocation. The block will be mapped by _RtlAllocateHeap. - assert(m_iMalloc != NULL); - block = (m_iMalloc) ? m_iMalloc->Alloc(size) : NULL; - - if (firstcall) - firstAllocCall(tls); - - return block; + LPVOID block; + context_t context; + tls_t *tls = getTls(); + + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + CAPTURE_CONTEXT(context); + tls->context = context; + tls->blockProcessed = FALSE; + } + + // Do the allocation. The block will be mapped by _RtlAllocateHeap. + assert(m_iMalloc != NULL); + block = (m_iMalloc) ? m_iMalloc->Alloc(size) : NULL; + + if (firstcall) + firstAllocCall(tls); + + return block; } // DidAlloc - Calls to IMalloc::DidAlloc will end up here. This function is just @@ -1979,8 +1980,8 @@ LPVOID VisualLeakDetector::Alloc (SIZE_T size) // INT VisualLeakDetector::DidAlloc (LPVOID mem) { - assert(m_iMalloc != NULL); - return (m_iMalloc) ? m_iMalloc->DidAlloc(mem) : 0; + assert(m_iMalloc != NULL); + return (m_iMalloc) ? m_iMalloc->DidAlloc(mem) : 0; } // Free - Calls to IMalloc::Free will end up here. This function is just a @@ -1994,8 +1995,8 @@ INT VisualLeakDetector::DidAlloc (LPVOID mem) // VOID VisualLeakDetector::Free (LPVOID mem) { - assert(m_iMalloc != NULL); - if (m_iMalloc) m_iMalloc->Free(mem); + assert(m_iMalloc != NULL); + if (m_iMalloc) m_iMalloc->Free(mem); } // GetSize - Calls to IMalloc::GetSize will end up here. This function is just a @@ -2010,8 +2011,8 @@ VOID VisualLeakDetector::Free (LPVOID mem) // SIZE_T VisualLeakDetector::GetSize (LPVOID mem) { - assert(m_iMalloc != NULL); - return (m_iMalloc) ? m_iMalloc->GetSize(mem) : 0; + assert(m_iMalloc != NULL); + return (m_iMalloc) ? m_iMalloc->GetSize(mem) : 0; } // HeapMinimize - Calls to IMalloc::HeapMinimize will end up here. This function @@ -2023,8 +2024,8 @@ SIZE_T VisualLeakDetector::GetSize (LPVOID mem) // VOID VisualLeakDetector::HeapMinimize () { - assert(m_iMalloc != NULL); - if (m_iMalloc) m_iMalloc->HeapMinimize(); + assert(m_iMalloc != NULL); + if (m_iMalloc) m_iMalloc->HeapMinimize(); } // QueryInterface - Calls to IMalloc::QueryInterface will end up here. This @@ -2043,8 +2044,8 @@ VOID VisualLeakDetector::HeapMinimize () // HRESULT VisualLeakDetector::QueryInterface (REFIID iid, LPVOID *object) { - assert(m_iMalloc != NULL); - return (m_iMalloc) ? m_iMalloc->QueryInterface(iid, object) : E_UNEXPECTED; + assert(m_iMalloc != NULL); + return (m_iMalloc) ? m_iMalloc->QueryInterface(iid, object) : E_UNEXPECTED; } // Realloc - Calls to IMalloc::Realloc will end up here. This function is just a @@ -2063,27 +2064,27 @@ HRESULT VisualLeakDetector::QueryInterface (REFIID iid, LPVOID *object) // LPVOID VisualLeakDetector::Realloc (LPVOID mem, SIZE_T size) { - LPVOID block; - context_t context; - tls_t *tls = getTls(); - - bool firstcall = (tls->context.fp == 0x0); - if (firstcall) { - // This is the first call to enter VLD for the current allocation. - // Record the current frame pointer. - CAPTURE_CONTEXT(context); - tls->context = context; - tls->blockProcessed = FALSE; - } - - // Do the allocation. The block will be mapped by _RtlReAllocateHeap. - assert(m_iMalloc != NULL); - block = (m_iMalloc) ? m_iMalloc->Realloc(mem, size) : NULL; - - if (firstcall) - firstAllocCall(tls); - - return block; + LPVOID block; + context_t context; + tls_t *tls = getTls(); + + bool firstcall = (tls->context.fp == 0x0); + if (firstcall) { + // This is the first call to enter VLD for the current allocation. + // Record the current frame pointer. + CAPTURE_CONTEXT(context); + tls->context = context; + tls->blockProcessed = FALSE; + } + + // Do the allocation. The block will be mapped by _RtlReAllocateHeap. + assert(m_iMalloc != NULL); + block = (m_iMalloc) ? m_iMalloc->Realloc(mem, size) : NULL; + + if (firstcall) + firstAllocCall(tls); + + return block; } // Release - Calls to IMalloc::Release will end up here. This function is just @@ -2096,6 +2097,6 @@ LPVOID VisualLeakDetector::Realloc (LPVOID mem, SIZE_T size) // ULONG VisualLeakDetector::Release () { - assert(m_iMalloc != NULL); - return (m_iMalloc) ? m_iMalloc->Release() : 0; + assert(m_iMalloc != NULL); + return (m_iMalloc) ? m_iMalloc->Release() : 0; }