diff --git a/CHANGES.txt b/CHANGES.txt index c180ae60..4bc7abe4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,6 +3,12 @@ Visual Leak Detector (VLD) Version 2.5.7 Change Log / Release Notes +2.5.9 (1 January 2023) +---------------------------- + Enhancements: + + Add option to ignore functions in vld.ini to skip checking for memory leaks. + + 2.5.8 (1 December 2021) ---------------------------- Bugs Fixed: diff --git a/setup/version.h b/setup/version.h index 5a938969..7154289b 100644 --- a/setup/version.h +++ b/setup/version.h @@ -1,9 +1,9 @@ -#define VLDVERSION L"2.5.8" -#define VERSION_NUMBER 2,5,8,0 -#define VERSION_STRING "2.5.8.0" +#define VLDVERSION L"2.5.9" +#define VERSION_NUMBER 2,5,9,0 +#define VERSION_STRING "2.5.9.0" #define VERSION_COPYRIGHT "Copyright (C) 2005-2021" #ifndef __FILE__ -!define VLD_VERSION "2.5.8" // NSIS Script +!define VLD_VERSION "2.5.9" // NSIS Script #endif diff --git a/setup/vld-setup.iss b/setup/vld-setup.iss index 6e3b2d85..bcb5de07 100644 --- a/setup/vld-setup.iss +++ b/setup/vld-setup.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "Visual Leak Detector" -#define MyAppVersion "2.5.8" +#define MyAppVersion "2.5.9" #define MyAppPublisher "VLD Team" #define MyAppURL "http://vld.codeplex.com/" #define MyAppRegKey "Software\Visual Leak Detector" diff --git a/src/callstack.cpp b/src/callstack.cpp index d2cf6ae6..c774eb4b 100644 --- a/src/callstack.cpp +++ b/src/callstack.cpp @@ -309,6 +309,10 @@ bool CallStack::isCrtStartupAlloc() return true; } else if (m_status & CALLSTACK_STATUS_NOTSTARTUPCRT) { return false; + } + + if (isIgnoreFunction(functionName)) { + return true; } } @@ -571,6 +575,14 @@ UINT CallStack::isCrtStartupFunction( LPCWSTR functionName ) const } return NULL; +} + +bool CallStack::isIgnoreFunction(LPCWSTR functionName) const +{ + if (VisualLeakDetector::isFunctionIgnored(functionName)) { + return true; + } + return false; } bool CallStack::isInternalModule( const PWSTR filename ) const diff --git a/src/callstack.h b/src/callstack.h index 9dfa353e..3b5f8634 100644 --- a/src/callstack.h +++ b/src/callstack.h @@ -126,6 +126,7 @@ class CallStack bool isInternalModule( const PWSTR filename ) const; UINT isCrtStartupFunction( LPCWSTR functionName ) const; + bool isIgnoreFunction(LPCWSTR functionName) const; LPCWSTR getFunctionName(SIZE_T programCounter, DWORD64& displacement64, SYMBOL_INFO* functionInfo, CriticalSectionLocker& locker) const; DWORD resolveFunction(SIZE_T programCounter, IMAGEHLP_LINEW64* sourceInfo, DWORD displacement, diff --git a/src/runtests.bat b/src/runtests.bat index a7058fc5..7c285425 100644 --- a/src/runtests.bat +++ b/src/runtests.bat @@ -30,11 +30,15 @@ ECHO --------------------------------------------------------------------------- ECHO [ RUNNING ] %tests_path%\vld_main_test.exe ECHO ------------------------------------------------------------------------------- !tests_path!\vld_main_test.exe --gtest_output="xml:!tests_path!\vld_main_test.exe.xml" -ECHO ------------------------------------------------------------------------------- +ECHO ------------------------------------------------------------------------------- ECHO [ RUNNING ] %tests_path%\static_string_test.exe ECHO ------------------------------------------------------------------------------- !tests_path!\static_string_test.exe --gtest_output="xml:!tests_path!\static_string_test.exe.xml" ECHO ------------------------------------------------------------------------------- +ECHO [ RUNNING ] %tests_path%\ignore_functions_test.exe +ECHO ------------------------------------------------------------------------------- +!tests_path!\static_string_test.exe --gtest_output="xml:!tests_path!\ignore_functions_test.exe.xml" +ECHO ------------------------------------------------------------------------------- EXIT /b 0 :nodir diff --git a/src/tests/ignore_functions_test/ignore_functions_test.cpp b/src/tests/ignore_functions_test/ignore_functions_test.cpp new file mode 100644 index 00000000..076d4b33 --- /dev/null +++ b/src/tests/ignore_functions_test/ignore_functions_test.cpp @@ -0,0 +1,37 @@ +// ignore_functions_test.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include "vld.h" +#include + + +std::string GetOSVersion() { + std::string osVersion = "Windows"; + return osVersion; +} + +std::string SomeOtherString() { + std::string osVersion = "Windows"; + return osVersion; +} + +int main(int argc, char** argv) +{ + static std::string const osVer = GetOSVersion(); + static std::string const someOtherString = SomeOtherString(); + + int leaks = static_cast(VLDGetLeaksCount()); + if (0 != leaks) + { + (void)printf("!!! FAILED - Leaks detected: %i\n", leaks); + VLDReportLeaks(); + } + else + { + (void)printf("PASSED\n"); + } + + + return leaks; +} diff --git a/src/tests/ignore_functions_test/ignore_functions_test.vcxproj b/src/tests/ignore_functions_test/ignore_functions_test.vcxproj new file mode 100644 index 00000000..681861f8 --- /dev/null +++ b/src/tests/ignore_functions_test/ignore_functions_test.vcxproj @@ -0,0 +1,342 @@ + + + + + Debug(Release)_StaticCrt + Win32 + + + Debug(Release)_StaticCrt + x64 + + + Debug(Release) + Win32 + + + Debug(Release) + x64 + + + Debug_StaticCrt + Win32 + + + Debug_StaticCrt + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release_StaticCrt + Win32 + + + Release_StaticCrt + x64 + + + Release + Win32 + + + Release + x64 + + + + {D1296F35-9834-4D72-94DC-7E1FD25D74D6} + Win32Proj + ignore_functions_test + ignore_functions_test + 10.0.19041.0 + + + + Application + Unicode + v142 + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + false + true + + + false + true + + + false + true + + + false + true + + + + + + + + + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + + + Console + true + + + + + Use + Level3 + Disabled + STATIC_CRT;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + MultiThreadedDebug + + + Console + true + + + + + Use + Level3 + Disabled + ProgramDatabase + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Use + Level3 + Disabled + STATIC_CRT;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + MultiThreadedDebug + + + Console + true + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + + + Console + true + + + + + Use + Level3 + Disabled + STATIC_CRT;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + MultiThreadedDebug + + + Console + true + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + + + Console + true + + + + + Use + Level3 + Disabled + STATIC_CRT;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + MultiThreadedDebug + + + Console + true + + + + + Level3 + Use + MaxSpeed + true + true + VLD_FORCE_ENABLE;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + STATIC_CRT;VLD_FORCE_ENABLE;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + + + Console + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + VLD_FORCE_ENABLE;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + STATIC_CRT;VLD_FORCE_ENABLE;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + + + Console + true + true + true + + + + + + + + + + Create + + + + + {c8f6c172-56f2-4e76-b5fa-c3b423b31be7} + + + + + + \ No newline at end of file diff --git a/src/tests/ignore_functions_test/ignore_functions_test.vcxproj.filters b/src/tests/ignore_functions_test/ignore_functions_test.vcxproj.filters new file mode 100644 index 00000000..8c3e2b05 --- /dev/null +++ b/src/tests/ignore_functions_test/ignore_functions_test.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/src/tests/ignore_functions_test/stdafx.cpp b/src/tests/ignore_functions_test/stdafx.cpp new file mode 100644 index 00000000..27f0ee01 --- /dev/null +++ b/src/tests/ignore_functions_test/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// basics.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/src/tests/ignore_functions_test/stdafx.h b/src/tests/ignore_functions_test/stdafx.h new file mode 100644 index 00000000..b005a839 --- /dev/null +++ b/src/tests/ignore_functions_test/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/src/tests/ignore_functions_test/targetver.h b/src/tests/ignore_functions_test/targetver.h new file mode 100644 index 00000000..87c0086d --- /dev/null +++ b/src/tests/ignore_functions_test/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/src/tests/ignore_functions_test/vld.ini b/src/tests/ignore_functions_test/vld.ini new file mode 100644 index 00000000..df498fcd --- /dev/null +++ b/src/tests/ignore_functions_test/vld.ini @@ -0,0 +1,184 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Visual Leak Detector - Initialization/Configuration File +;; Copyright (c) 2005-2017 VLD Team +;; +;; This library is free software; you can redistribute it and/or +;; modify it under the terms of the GNU Lesser General Public +;; License as published by the Free Software Foundation; either +;; version 2.1 of the License, or (at your option) any later version. +;; +;; This library is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public +;; License along with this library; if not, write to the Free Software +;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +;; +;; See COPYING.txt for the full terms of the GNU Lesser General Public License. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Any options left blank or not present will revert to their default values. +[Options] + +; The main on/off switch. If off, Visual Leak Detector will be completely +; disabled. It will do nothing but print a message to the debugger indicating +; that it has been turned off. +; +; Valid Values: on, off +; Default: on +; +VLD = on + +; If yes, duplicate leaks (those that are identical) are not shown individually. +; Only the first such leak is shown, along with a number indicating the total +; number of duplicate leaks. +; +; Valid Values: yes, no +; Default: no +; +AggregateDuplicates = no + +; Lists any additional modules to be included in memory leak detection. This can +; be useful for checking for memory leaks in debug builds of 3rd party modules +; which can not be easily rebuilt with '#include "vld.h"'. This option should be +; used only if absolutely necessary and only if you really know what you are +; doing. +; +; CAUTION: Avoid listing any modules that link with the release CRT libraries. +; Only modules that link with the debug CRT libraries should be listed here. +; Doing otherwise might result in false memory leak reports or even crashes. +; +; Valid Values: Any list containing module names (i.e. names of EXEs or DLLs) +; Default: None. +; +ForceIncludeModules = + +; Maximum number of data bytes to display for each leaked block. If zero, then +; the data dump is completely suppressed and only call stacks are shown. +; Limiting this to a low number can be useful if any of the leaked blocks are +; very large and cause unnecessary clutter in the memory leak report. +; +; Value Values: 0 - 4294967295 +; Default: 256 +; +MaxDataDump = + +; Maximum number of call stack frames to trace back during leak detection. +; Limiting this to a low number can reduce the CPU utilization overhead imposed +; by memory leak detection, especially when using the slower "safe" stack +; walking method (see StackWalkMethod below). +; +; Valid Values: 1 - 4294967295 +; Default: 64 +; +MaxTraceFrames = + +; Sets the type of encoding to use for the generated memory leak report. This +; option is really only useful in conjuction with sending the report to a file. +; Sending a Unicode encoded report to the debugger is not useful because the +; debugger cannot display Unicode characters. Using Unicode encoding might be +; useful if the data contained in leaked blocks is likely to consist of Unicode +; text. +; +; Valid Values: ascii, unicode +; Default: ascii +; +ReportEncoding = ascii + +; Sets the report file destination, if reporting to file is enabled. A relative +; path may be specified and is considered relative to the process' working +; directory. +; +; Valid Values: Any valid path and filename. +; Default: .\memory_leak_report.txt +; +ReportFile = + +; Sets the report destination to either a file, the debugger, or both. If +; reporting to file is enabled, the report is sent to the file specified by the +; ReportFile option. +; +; Valid Values: debugger, file, both +; Default: debugger +; +ReportTo = debugger + +; Turns on or off a self-test mode which is used to verify that VLD is able to +; detect memory leaks in itself. Intended to be used for debugging VLD itself, +; not for debugging other programs. +; +; Valid Values: on, off +; Default: off +; +SelfTest = off + +; Selects the method to be used for walking the stack to obtain stack traces for +; allocated memory blocks. The "fast" method may not always be able to +; successfully trace completely through all call stacks. In such cases, the +; "safe" method may prove to more reliably obtain the full stack trace. The +; disadvantage is that the "safe" method is significantly slower than the "fast" +; method and will probably result in very noticeable performance degradation of +; the program being debugged. +; +; Valid Values: fast, safe +; Default: fast +; +StackWalkMethod = fast + +; Determines whether memory leak detection should be initially enabled for all +; threads, or whether it should be initially disabled for all threads. If set +; to "yes", then any threads requiring memory leak detection to be enabled will +; need to call VLDEnable at some point to enable leak detection for those +; threads. +; +; Valid Values: yes, no +; Default: no +; +StartDisabled = no + +; Determines whether or not all frames, including frames internal to the heap, +; are traced. There will always be a number of frames internal to Visual Leak +; Detector and C/C++ or Win32 heap APIs that aren't generally useful for +; determining the cause of a leak. Normally these frames are skipped during the +; stack trace, which somewhat reduces the time spent tracing and amount of data +; collected and stored in memory. Including all frames in the stack trace, all +; the way down into VLD's own code can, however, be useful for debugging VLD +; itself. +; +; Valid Values: yes, no +; Default: no +; +TraceInternalFrames = no + +; Determines whether or not report memory leaks when missing HeapFree calls. +; +; Valid Values: yes, no +; Default: no +; +SkipHeapFreeLeaks = no + +; Determines whether or not report memory leaks generated from crt startup code. +; These are not actual memory leaks as they are freed by crt after the VLD object +; has been destroyed. +; +; Valid Values: yes, no +; Default: yes +; +SkipCrtStartupLeaks = yes + +; Lists any specific functions to be ignored in memory leak detection. This can +; be useful for false positive functions that report memory leaks especially +; when the code is maintained by 3rd party libraries. This option should be +; used only if absolutely necessary and only if you really know what you are +; doing. +; +; CAUTION: Avoid listing any function names without manually checking for leaks. +; +; Valid Values: Functions names as strings separated by comma. Strings are case sensitive. +; Default: None. +; +IgnoreFunctionsList = GetOSVersion,SomeOtherString \ No newline at end of file diff --git a/src/vld.cpp b/src/vld.cpp index 66e00507..2d12feb8 100644 --- a/src/vld.cpp +++ b/src/vld.cpp @@ -343,6 +343,7 @@ VisualLeakDetector::VisualLeakDetector () // Initialize configuration options and related private data. _wcsnset_s(m_forcedModuleList, MAXMODULELISTLENGTH, '\0', _TRUNCATE); + m_maxDataDump = 0xffffffff; m_maxTraceFrames = 0xffffffff; m_options = 0x0; @@ -452,6 +453,16 @@ VisualLeakDetector::VisualLeakDetector () // debugger gets lost if it's sent too fast). InsertReportDelay(); } + if (m_options & VLD_OPT_IGNORE_FUNCTIONS) { + // Delimit each function name with "," and insert these into IgnoreFunctionsSet. + LPCWSTR pwc; + wchar_t* buffer; + pwc = wcstok_s(m_ignoreFunctionsList, L",", &buffer); + while (pwc != NULL) { + m_ignoreFunctions.insert(pwc); + pwc = wcstok_s(NULL, L",", &buffer); + } + } // This is highly unlikely to happen, but just in case, check to be sure // we got a valid TLS index. @@ -1160,6 +1171,13 @@ VOID VisualLeakDetector::configure () else m_options |= VLD_OPT_MODULE_LIST_INCLUDE; + // Read the ignore function list. + LoadStringOption(L"IgnoreFunctionsList", m_ignoreFunctionsList, MAXIGNOREFUNCTIONLISTLENGTH, inipath); + if (wcscmp(m_ignoreFunctionsList, L"") == 0) + m_ignoreFunctionsList[0] = '\0'; + else + m_options |= VLD_OPT_IGNORE_FUNCTIONS; + // Read the report destination (debugger, file, or both). WCHAR filename [MAX_PATH] = {0}; LoadStringOption(L"ReportFile", filename, MAX_PATH, inipath); @@ -1676,6 +1694,9 @@ VOID VisualLeakDetector::reportConfig () if (m_options & VLD_OPT_TRACE_INTERNAL_FRAMES) { Report(L" Including heap and VLD internal frames in stack traces.\n"); } + if (m_options & VLD_OPT_IGNORE_FUNCTIONS) { + Report(L" Ignorning these functions from leak detection: %s\n", m_ignoreFunctionsList); + } } bool VisualLeakDetector::isDebugCrtAlloc( LPCVOID block, blockinfo_t* info ) @@ -2353,6 +2374,12 @@ bool VisualLeakDetector::isModuleExcluded(UINT_PTR address) return false; } + +bool VisualLeakDetector::isFunctionIgnored(LPCWSTR functionName) +{ + return g_vld.m_ignoreFunctions.find(functionName) != g_vld.m_ignoreFunctions.end(); +} + SIZE_T VisualLeakDetector::GetLeaksCount() { if (m_options & VLD_OPT_VLDOFF) { @@ -2604,7 +2631,7 @@ void VisualLeakDetector::GlobalEnableLeakDetection () CONST UINT32 OptionsMask = VLD_OPT_AGGREGATE_DUPLICATES | VLD_OPT_MODULE_LIST_INCLUDE | VLD_OPT_SAFE_STACK_WALK | VLD_OPT_SLOW_DEBUGGER_DUMP | VLD_OPT_START_DISABLED | VLD_OPT_TRACE_INTERNAL_FRAMES | VLD_OPT_SKIP_HEAPFREE_LEAKS | VLD_OPT_VALIDATE_HEAPFREE | - VLD_OPT_SKIP_CRTSTARTUP_LEAKS; + VLD_OPT_SKIP_CRTSTARTUP_LEAKS | VLD_OPT_IGNORE_FUNCTIONS; UINT32 VisualLeakDetector::GetOptions() { diff --git a/src/vld_def.h b/src/vld_def.h index 265de49c..c4e49dfc 100644 --- a/src/vld_def.h +++ b/src/vld_def.h @@ -42,6 +42,7 @@ #define VLD_OPT_SKIP_HEAPFREE_LEAKS 0x1000 // If set, VLD skip HeapFree memory leaks. #define VLD_OPT_VALIDATE_HEAPFREE 0x2000 // If set, VLD verifies and reports heap consistency for HeapFree calls. #define VLD_OPT_SKIP_CRTSTARTUP_LEAKS 0x4000 // If set, VLD skip crt srtartup memory leaks. +#define VLD_OPT_IGNORE_FUNCTIONS 0x8000 // If set, VLD skips the defined functions in IgnoreFunctionsList. #define VLD_RPTHOOK_INSTALL 0 #define VLD_RPTHOOK_REMOVE 1 diff --git a/src/vldint.h b/src/vldint.h index 05cec209..c5a535aa 100644 --- a/src/vldint.h +++ b/src/vldint.h @@ -35,6 +35,7 @@ #include #include #pragma pop_macro("new") +#include #include #include "vld_def.h" #include "version.h" @@ -46,6 +47,7 @@ #include "vldallocator.h" // Provides internal allocator. #define MAXMODULELISTLENGTH 512 // Maximum module list length, in characters. +#define MAXIGNOREFUNCTIONLISTLENGTH 2048 // Maximum module list length, in characters. #define SELFTESTTEXTA "Memory Leak Self-Test" #define SELFTESTTEXTW L"Memory Leak Self-Test" #define VLDREGKEYPRODUCT L"Software\\Visual Leak Detector" @@ -156,6 +158,14 @@ typedef Set ModuleSet; typedef Set ReportHookSet; + +struct LPCWSTRComparator { + bool operator()(LPCWSTR a, LPCWSTR b) const { + return lstrcmpW(a, b) > 0; + } +}; +typedef std::set IgnoreFunctionsSet; + // Thread local storage structure. Every thread in the process gets its own copy // of this structure. Thread specific information, such as the current leak // detection status (enabled or disabled) and the address that initiated the @@ -324,6 +334,7 @@ class VisualLeakDetector : public IMalloc // Utils static bool isModuleExcluded (UINT_PTR returnaddress); + static bool isFunctionIgnored(LPCWSTR functionName); blockinfo_t* findAllocedBlock(LPCVOID, __out HANDLE& heap); blockinfo_t* getAllocationBlockInfo(void* alloc); void setupReporting(); @@ -362,6 +373,7 @@ class VisualLeakDetector : public IMalloc // Private data //////////////////////////////////////////////////////////////////////////////// WCHAR m_forcedModuleList [MAXMODULELISTLENGTH]; // List of modules to be forcefully included in leak detection. + WCHAR m_ignoreFunctionsList [MAXIGNOREFUNCTIONLISTLENGTH]; // List of functions to be ignored in leak detection. HeapMap *m_heapMap; // Map of all active heaps in the process. IMalloc *m_iMalloc; // Pointer to the system implementation of IMalloc. @@ -375,6 +387,7 @@ class VisualLeakDetector : public IMalloc CriticalSection m_modulesLock; // Protects accesses to the "loaded modules" ModuleSet. CriticalSection m_optionsLock; // Serializes access to the heap and block maps. UINT32 m_options; // Configuration options. + IgnoreFunctionsSet m_ignoreFunctions; // Contains information about all the functions that needs to be ignored. static patchentry_t m_kernelbasePatch []; static patchentry_t m_kernel32Patch []; diff --git a/vld.ini b/vld.ini index fa501129..4c613141 100644 --- a/vld.ini +++ b/vld.ini @@ -169,3 +169,16 @@ SkipHeapFreeLeaks = no ; Default: yes ; SkipCrtStartupLeaks = yes + +; Lists any specific functions to be ignored in memory leak detection. This can +; be useful for false positive functions that report memory leaks especially +; when the code is maintained by 3rd party libraries. This option should be +; used only if absolutely necessary and only if you really know what you are +; doing. +; +; CAUTION: Avoid listing any function names without manually checking for leaks. +; +; Valid Values: Functions names as strings separated by comma. Strings are case sensitive. +; Default: None. +; +IgnoreFunctionsList = \ No newline at end of file diff --git a/vld_vs14.sln b/vld_vs14.sln index d74a1fe5..75d57f74 100644 --- a/vld_vs14.sln +++ b/vld_vs14.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30523.141 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33103.184 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vld", "src\vld.vcxproj", "{0D30FFCB-45DA-4D2B-8E3C-81BC145BF2DE}" EndProject @@ -73,6 +73,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vld_main_test", "src\tests\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "static_string_test", "src\tests\static_string_test\static_string_test.vcxproj", "{530901ED-6D5A-4BCF-9925-66F5DD51C610}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ignore_functions_test", "src\tests\ignore_functions_test\ignore_functions_test.vcxproj", "{D1296F35-9834-4D72-94DC-7E1FD25D74D6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug(Release)_StaticCrt|Win32 = Debug(Release)_StaticCrt|Win32 @@ -638,6 +640,38 @@ Global {530901ED-6D5A-4BCF-9925-66F5DD51C610}.Release|Win32.Build.0 = Release|Win32 {530901ED-6D5A-4BCF-9925-66F5DD51C610}.Release|x64.ActiveCfg = Release|x64 {530901ED-6D5A-4BCF-9925-66F5DD51C610}.Release|x64.Build.0 = Release|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug(Release)_StaticCrt|Win32.ActiveCfg = Debug(Release)_StaticCrt|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug(Release)_StaticCrt|Win32.Build.0 = Debug(Release)_StaticCrt|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug(Release)_StaticCrt|x64.ActiveCfg = Debug(Release)_StaticCrt|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug(Release)_StaticCrt|x64.Build.0 = Debug(Release)_StaticCrt|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug(Release)|Win32.ActiveCfg = Debug(Release)|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug(Release)|Win32.Build.0 = Debug(Release)|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug(Release)|x64.ActiveCfg = Debug(Release)|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug(Release)|x64.Build.0 = Debug(Release)|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug_StaticCrt|Win32.ActiveCfg = Debug_StaticCrt|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug_StaticCrt|Win32.Build.0 = Debug_StaticCrt|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug_StaticCrt|x64.ActiveCfg = Debug_StaticCrt|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug_StaticCrt|x64.Build.0 = Debug_StaticCrt|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug_VldRelease_StaticCrt|Win32.ActiveCfg = Debug(Release)_StaticCrt|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug_VldRelease_StaticCrt|Win32.Build.0 = Debug(Release)_StaticCrt|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug_VldRelease_StaticCrt|x64.ActiveCfg = Debug(Release)_StaticCrt|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug_VldRelease_StaticCrt|x64.Build.0 = Debug(Release)_StaticCrt|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug_VldRelease|Win32.ActiveCfg = Debug(Release)_StaticCrt|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug_VldRelease|Win32.Build.0 = Debug(Release)_StaticCrt|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug_VldRelease|x64.ActiveCfg = Debug(Release)_StaticCrt|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug_VldRelease|x64.Build.0 = Debug(Release)_StaticCrt|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug|Win32.ActiveCfg = Debug|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug|Win32.Build.0 = Debug|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug|x64.ActiveCfg = Debug|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Debug|x64.Build.0 = Debug|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Release_StaticCrt|Win32.ActiveCfg = Release_StaticCrt|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Release_StaticCrt|Win32.Build.0 = Release_StaticCrt|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Release_StaticCrt|x64.ActiveCfg = Release_StaticCrt|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Release_StaticCrt|x64.Build.0 = Release_StaticCrt|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Release|Win32.ActiveCfg = Release|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Release|Win32.Build.0 = Release|Win32 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Release|x64.ActiveCfg = Release|x64 + {D1296F35-9834-4D72-94DC-7E1FD25D74D6}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -661,6 +695,7 @@ Global {3719F504-3DF0-45F8-BC7A-4415804AC7C9} = {9F9CFA3A-F154-4069-89E3-19BDC6BD3A7D} {BB99EDE9-D039-4169-B26B-6BFD93C6AF8E} = {9F9CFA3A-F154-4069-89E3-19BDC6BD3A7D} {530901ED-6D5A-4BCF-9925-66F5DD51C610} = {9F9CFA3A-F154-4069-89E3-19BDC6BD3A7D} + {D1296F35-9834-4D72-94DC-7E1FD25D74D6} = {9F9CFA3A-F154-4069-89E3-19BDC6BD3A7D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BBE80701-4516-4F15-8A85-6E07373C642B}