Problem with memory leak display in VS 2015
In Visual Studio 2015, /DEBUG:FASTLINK, instead of /DEBUG, is available thru Properties > Linker > Generate Debugging Info. When used without /LTCG (as it usually is for debug) it will generate a partial PDB file. This condition is displayed in the Output window when the PDB file is generated during linking. The linker will display either (Full PDB) or (Partial PDB). If a partial PDB is generated, Visual Leak Detector may not display the necessary debugging information. The problem can be intermittent, working sometimes and not others. An example of incomplete memory leak information using /DEBUG:FASTLINK and (Partial PDB) is:
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 54863 at 0x00D3A1F8: 100 bytes ----------
Leak Hash: 0x324E4B97, Count: 1, Total 100 bytes
Call Stack (TID 5896):
ucrtbased.dll!malloc()
AStyleTestl.exe!0x0040017D()
AStyleTestl.exe!0x004027FC()
AStyleTestl.exe!0x00400840()
AStyleTestl.exe!0x0037ED13()
AStyleTestl.exe!0x0012787F()
AStyleTestl.exe!0x003DF466()
AStyleTestl.exe!0x003DEDDD()
AStyleTestl.exe!0x003C79AE()
AStyleTestl.exe!0x003C835D()
AStyleTestl.exe!0x003C897F()
AStyleTestl.exe!0x003CEABC()
AStyleTestl.exe!0x003DF78C()
AStyleTestl.exe!0x003DF2CD()
AStyleTestl.exe!0x003C8FF1()
AStyleTestl.exe!0x002577AF()
AStyleTestl.exe!0x00256C10()
AStyleTestl.exe!0x00400BDE()
AStyleTestl.exe!0x00400AAA()
AStyleTestl.exe!0x0040094D()
AStyleTestl.exe!0x00400BF8()
KERNEL32.DLL!BaseThreadInitThunk() + 0x24 bytes
ntdll.dll!RtlUnicodeStringToInteger() + 0x253 bytes
ntdll.dll!RtlUnicodeStringToInteger() + 0x21E bytes
Using /DEBUG and (Full PDB) the memory leak display is correct. The leak is at astyle_main.cpp line 3709 in the following:
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 54863 at 0x0067FB88: 100 bytes ----------
Leak Hash: 0x2D9D7EB5, Count: 1, Total 100 bytes
Call Stack (TID 6936):
ucrtbased.dll!malloc()
f:\dd\vctools\crt\vcstartup\src\heap\new_scalar.cpp (19): AStyleTestl.exe!operator new() + 0x9 bytes
f:\dd\vctools\crt\vcstartup\src\heap\new_scalar_nothrow.cpp (17): AStyleTestl.exe!operator new() + 0x9 bytes
f:\dd\vctools\crt\vcstartup\src\heap\new_array_nothrow.cpp (15): AStyleTestl.exe!operator new[]() + 0xD bytes
c:\users\jimp\projects\astyle\src\astyle_main.cpp (3709): AStyleTestl.exe!AStyleMain() + 0xC bytes
c:\users\jimp\projects\astyletest\src\astyletest_alignpointer.cpp (40): AStyleTestl.exe!`anonymous namespace'::AlignPointerNone_LongOption_Test::TestBody() + 0x1D bytes
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2063): AStyleTestl.exe!testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test,void>() + 0x8 bytes
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2114): AStyleTestl.exe!testing::internal::HandleExceptionsInMethodIfSupported<testing::Test,void>() + 0x11 bytes
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2150): AStyleTestl.exe!testing::Test::Run() + 0x13 bytes
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2330): AStyleTestl.exe!testing::TestInfo::Run()
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2445): AStyleTestl.exe!testing::TestCase::Run()
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (4316): AStyleTestl.exe!testing::internal::UnitTestImpl::RunAllTests()
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2063): AStyleTestl.exe!testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl,bool>() + 0x8 bytes
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2114): AStyleTestl.exe!testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl,bool>() + 0x11 bytes
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (3926): AStyleTestl.exe!testing::UnitTest::Run() + 0x18 bytes
c:\users\jimp\projects\gmock\gtest\include\gtest\gtest.h (2289): AStyleTestl.exe!RUN_ALL_TESTS()
c:\users\jimp\projects\astyletest\src\astyletest_main.cpp (60): AStyleTestl.exe!main() + 0x5 bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (74): AStyleTestl.exe!invoke_main() + 0x1B bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (264): AStyleTestl.exe!__scrt_common_main_seh() + 0x5 bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (309): AStyleTestl.exe!__scrt_common_main()
f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp (17): AStyleTestl.exe!mainCRTStartup()
KERNEL32.DLL!BaseThreadInitThunk() + 0x24 bytes
ntdll.dll!RtlUnicodeStringToInteger() + 0x253 bytes
ntdll.dll!RtlUnicodeStringToInteger() + 0x21E bytes
With /DEBUG:FASTLINK the linker produced PDB doesn't have any private symbol, and debug information is distributed among input object and library files and the linker generated PDB just serves as an indexing database. See http://blogs.msdn.com/b/vcblog/archive/2015/10/16/debug-fastlink-for-vs2015-update-1.aspx.
The temporary fix is obviously to use /DEBUG instead of /DEBUG:FASTLINK when using the leak detector. But a better solution would be to display the correct information when /DEBUG:FASTLINK is used. This may be a fairly time-consuming change. But it would allow users to use /DEBUG:FASTLINK in their compile.
In Visual Studio 2015, /DEBUG:FASTLINK, instead of /DEBUG, is available thru Properties > Linker > Generate Debugging Info. When used without /LTCG (as it usually is for debug) it will generate a partial PDB file. This condition is displayed in the Output window when the PDB file is generated during linking. The linker will display either (Full PDB) or (Partial PDB). If a partial PDB is generated, Visual Leak Detector may not display the necessary debugging information. The problem can be intermittent, working sometimes and not others. An example of incomplete memory leak information using /DEBUG:FASTLINK and (Partial PDB) is:
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 54863 at 0x00D3A1F8: 100 bytes ----------
Leak Hash: 0x324E4B97, Count: 1, Total 100 bytes
Call Stack (TID 5896):
ucrtbased.dll!malloc()
AStyleTestl.exe!0x0040017D()
AStyleTestl.exe!0x004027FC()
AStyleTestl.exe!0x00400840()
AStyleTestl.exe!0x0037ED13()
AStyleTestl.exe!0x0012787F()
AStyleTestl.exe!0x003DF466()
AStyleTestl.exe!0x003DEDDD()
AStyleTestl.exe!0x003C79AE()
AStyleTestl.exe!0x003C835D()
AStyleTestl.exe!0x003C897F()
AStyleTestl.exe!0x003CEABC()
AStyleTestl.exe!0x003DF78C()
AStyleTestl.exe!0x003DF2CD()
AStyleTestl.exe!0x003C8FF1()
AStyleTestl.exe!0x002577AF()
AStyleTestl.exe!0x00256C10()
AStyleTestl.exe!0x00400BDE()
AStyleTestl.exe!0x00400AAA()
AStyleTestl.exe!0x0040094D()
AStyleTestl.exe!0x00400BF8()
KERNEL32.DLL!BaseThreadInitThunk() + 0x24 bytes
ntdll.dll!RtlUnicodeStringToInteger() + 0x253 bytes
ntdll.dll!RtlUnicodeStringToInteger() + 0x21E bytes
Using /DEBUG and (Full PDB) the memory leak display is correct. The leak is at astyle_main.cpp line 3709 in the following:
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 54863 at 0x0067FB88: 100 bytes ----------
Leak Hash: 0x2D9D7EB5, Count: 1, Total 100 bytes
Call Stack (TID 6936):
ucrtbased.dll!malloc()
f:\dd\vctools\crt\vcstartup\src\heap\new_scalar.cpp (19): AStyleTestl.exe!operator new() + 0x9 bytes
f:\dd\vctools\crt\vcstartup\src\heap\new_scalar_nothrow.cpp (17): AStyleTestl.exe!operator new() + 0x9 bytes
f:\dd\vctools\crt\vcstartup\src\heap\new_array_nothrow.cpp (15): AStyleTestl.exe!operator new[]() + 0xD bytes
c:\users\jimp\projects\astyle\src\astyle_main.cpp (3709): AStyleTestl.exe!AStyleMain() + 0xC bytes
c:\users\jimp\projects\astyletest\src\astyletest_alignpointer.cpp (40): AStyleTestl.exe!`anonymous namespace'::AlignPointerNone_LongOption_Test::TestBody() + 0x1D bytes
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2063): AStyleTestl.exe!testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test,void>() + 0x8 bytes
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2114): AStyleTestl.exe!testing::internal::HandleExceptionsInMethodIfSupported<testing::Test,void>() + 0x11 bytes
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2150): AStyleTestl.exe!testing::Test::Run() + 0x13 bytes
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2330): AStyleTestl.exe!testing::TestInfo::Run()
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2445): AStyleTestl.exe!testing::TestCase::Run()
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (4316): AStyleTestl.exe!testing::internal::UnitTestImpl::RunAllTests()
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2063): AStyleTestl.exe!testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl,bool>() + 0x8 bytes
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (2114): AStyleTestl.exe!testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl,bool>() + 0x11 bytes
c:\users\jimp\projects\gmock\gtest\src\gtest.cc (3926): AStyleTestl.exe!testing::UnitTest::Run() + 0x18 bytes
c:\users\jimp\projects\gmock\gtest\include\gtest\gtest.h (2289): AStyleTestl.exe!RUN_ALL_TESTS()
c:\users\jimp\projects\astyletest\src\astyletest_main.cpp (60): AStyleTestl.exe!main() + 0x5 bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (74): AStyleTestl.exe!invoke_main() + 0x1B bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (264): AStyleTestl.exe!__scrt_common_main_seh() + 0x5 bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (309): AStyleTestl.exe!__scrt_common_main()
f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp (17): AStyleTestl.exe!mainCRTStartup()
KERNEL32.DLL!BaseThreadInitThunk() + 0x24 bytes
ntdll.dll!RtlUnicodeStringToInteger() + 0x253 bytes
ntdll.dll!RtlUnicodeStringToInteger() + 0x21E bytes
With /DEBUG:FASTLINK the linker produced PDB doesn't have any private symbol, and debug information is distributed among input object and library files and the linker generated PDB just serves as an indexing database. See http://blogs.msdn.com/b/vcblog/archive/2015/10/16/debug-fastlink-for-vs2015-update-1.aspx.
The temporary fix is obviously to use /DEBUG instead of /DEBUG:FASTLINK when using the leak detector. But a better solution would be to display the correct information when /DEBUG:FASTLINK is used. This may be a fairly time-consuming change. But it would allow users to use /DEBUG:FASTLINK in their compile.