Visual Studio 2017 – Why can’t I see the local and auto variables during UWP app debugging?

I’d like to share my short episode regarding UWP app debugging which happened today. Recent days I’ve developed a WinRT dynamic library which is based on cppwinrt. Most of time, I tested it with an unittest project and everything went fine. However, when I used the WinRT dll from actual .exe UWP application then very strange problem showed up.

As you see the below screenshots, the Visual Studio 2017 debugger shows nothing about local variables, auto and even watch window variables during the UWP app debugging.

Moreover, if I tried to type specific variables into Watch window or immediate window, the debugger shows ‘Internal error in the C# compiler‘ error message!

Later I noticed that the strange problem starts just right after the following output messages come up from Output window.

‘Example.exe’ (CoreCLR: CoreCLR_UWP_Domain): Loaded ‘Anonymously Hosted DynamicMethods Assembly’.

‘Example.exe’ (Win32): Loaded ‘C:\src\Example\build\Win32\Debug\AppX\Example.winmd’. Module was built without symbols.

‘Example.exe’ (CoreCLR: CoreCLR_UWP_Domain): Loaded ‘C:\src\Example\build\Win32\Debug\AppX\Example.winmd’. Module was built without symbols.

How just loading .winmd file could affect the weird debugger problem? Then I realized I used the same name(‘Example’) for the application and the WinRT module both. Which means I created the WinRT dll component as ‘Example.DLL’ and along with ‘Example.winmd’ as its descriptive winmd file name, of course. But I also named the target UWP application as ‘Example’.

So while debugging, the debugger tried to load the winmd file for it’s target WinRT component which was being debugged and suddenly the namespace seemed clashed within between the app and debugee DLL.

So, I changed the name of the WinRT component as ‘Example.Library.dll’ and problem solved!



CppRest SDK(Casablanca) + static CRT link = caution! (might cause debug heap assert)

The C++ REST SDK(Casablanca) is currently only available to link dynamically(DLL) unless you build the library on your own. Here is the link describing the steps to link static to your application by downloading the source code and building it so.

If you’re using the cpprest sdk and unfortunately encountered the following debug heap assert, you probably made mismatch configuration for the Configuration Properties > C/C++ > Code Generation > Runtime Library for your main application against the cpprest DLL.

————————— Microsoft Visual C++ Runtime Library —————————

Debug Assertion Failed!

Program: C:\repo\test\cppresttest\Debug\cppresttest.exe File: f:\dd\vctools\crt\crtw32\misc\dbgheap.c Line: 1424

Expression: _pFirstBlock == pHead

For information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts.

debug heap assert
debug heap assert

The above link contains code snippet shows how simple cpprest is to read json value from STL fstream. However, if you run the code with Multi-threaded(/MT) enabled then it’ll end with a debug assert just right after the temporary std::wstring object as_string() returned is about to clean up itself.

In order to see what actually happened inside it, I enabled the gflag PeageHeap and captured a dump when the popup showed.

0:000> .frame 3
03 00ccf280 002b8cc3 cppresttest!std::allocator::deallocate+0x2c [c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0 @ 573]
0:000> dv
this = 0x00ccf397
_Ptr = 0x05ab0fb8 “what do you think for this”
__formal = 0x20
0:000> !heap -p -a 0x05ab0fb8
address 05ab0fb8 found in
_DPH_HEAP_ROOT @ 5621000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize – VirtAddr VirtSize)
56247b8: 5ab0f98 64 – 5ab0000 2000
523b94ec verifier!AVrfDebugPageHeapAllocate+0x0000023c
77c557b7 ntdll!RtlDebugAllocateHeap+0x0000003c
77bf77ce ntdll!RtlpAllocateHeap+0x0004665a
77bb1134 ntdll!RtlAllocateHeap+0x0000014d
5151c6e1 MSVCR120D!_heap_alloc_base+0x00000051 [f:\dd\vctools\crt\crtw32\heap\malloc.c @ 58]
5152d72f MSVCR120D!_heap_alloc_dbg_impl+0x000001ff [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 431]
5152dbcd MSVCR120D!_nh_malloc_dbg_impl+0x0000001d [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 239]
5152db7a MSVCR120D!_nh_malloc_dbg+0x0000002a [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 302]
5152e5a9 MSVCR120D!malloc+0x00000019 [f:\dd\vctools\crt\crtw32\misc\dbgmalloc.c @ 56]
5151c26f MSVCR120D!operator new+0x0000000f [f:\dd\vctools\crt\crtw32\heap\new.cpp @ 59]
*** ERROR: Symbol file could not be found. Defaulted to export symbols for cpprest120d_2_5.dll –
10094601 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x00017cc3
100a186e cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x00024f30
100a16ef cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x00024db1
1009eb54 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x00022216
1009f8d6 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x00022f98
100a1da9 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x0002546b
10099e7f cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x0001d541
1022c95c cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001b001e
1022c9f4 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001b00b6
002bd377 cppresttest!wmain+0x00000237 [c:\repo\test\cppresttest\cppresttest\cppresttest.cpp @ 26]
0030c62a cppresttest!__tmainCRTStartup+0x0000011a [f:\dd\vctools\crt\crtw32\startup\crt0.c @ 255]
0030c80d cppresttest!wmainCRTStartup+0x0000000d [f:\dd\vctools\crt\crtw32\startup\crt0.c @ 165]
77897c04 kernel32!BaseThreadInitThunk+0x00000024
77bcad1f ntdll!__RtlUserThreadStart+0x0000002f
77bcacea ntdll!_RtlUserThreadStart+0x0000001b

_Ptr is the pHead and the call stack clearly shows it was allocated from the heap of MSVCR120D DLL. However, the another heap start address(_pFirstBlock) which failed to assert to be equal shows it’s allocated from different heap which was statically linked CRT more specifically.

00 00ccf128 00309bee cppresttest!_free_dbg_nolock+0x49d [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 1424]
0:000> !heap -p -a 0x092d6fd8
address 092d6fd8 found in
_DPH_HEAP_ROOT @ 5621000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize – VirtAddr VirtSize)
91e2680: 92d6fd8 1024 – 92d6000 3000
523b94ec verifier!AVrfDebugPageHeapAllocate+0x0000023c
77c557b7 ntdll!RtlDebugAllocateHeap+0x0000003c
77bf77ce ntdll!RtlpAllocateHeap+0x0004665a
77bb1134 ntdll!RtlAllocateHeap+0x0000014d
00325da1 cppresttest!_heap_alloc_base+0x00000051 [f:\dd\vctools\crt\crtw32\heap\malloc.c @ 58]
0030a52f cppresttest!_heap_alloc_dbg_impl+0x000001ff [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 431]
0030ab9d cppresttest!_nh_malloc_dbg_impl+0x0000001d [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 239]
0030ab3a cppresttest!_nh_malloc_dbg+0x0000002a [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 302]
0030a7ff cppresttest!_malloc_dbg+0x0000001f [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 160]
0031d887 cppresttest!_getbuf+0x00000057 [f:\dd\vctools\crt\crtw32\stdio\_getbuf.c @ 58]
0031bd36 cppresttest!_filbuf+0x000000f6 [f:\dd\vctools\crt\crtw32\stdio\_filbuf.c @ 130]
00302643 cppresttest!fgetc+0x00000223 [f:\dd\vctools\crt\crtw32\stdio\fgetc.c @ 49]
002af947 cppresttest!std::_Fgetc+0x00000027 [c:\program files (x86)\microsoft visual studio 12.0\vc\include\fstream @ 39]
002bc2c7 cppresttest!std::basic_filebuf<char,std::char_traits >::uflow+0x000000b7 [c:\program files (x86)\microsoft visual studio 12.0\vc\include\fstream @ 478]
51fe7598 MSVCP120D!std::basic_streambuf<char,std::char_traits >::sbumpc+0x00000048 [f:\dd\vctools\crt\crtw32\stdhpp\streambuf @ 147]
10223aa1 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001a7163
102230a1 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001a6763
1022321b cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001a68dd
102281d1 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001ab893
10229b05 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001ad1c7
002bd238 cppresttest!wmain+0x000000f8 [c:\repo\test\cppresttest\cppresttest\cppresttest.cpp @ 22]
0030c62a cppresttest!__tmainCRTStartup+0x0000011a [f:\dd\vctools\crt\crtw32\startup\crt0.c @ 255]
0030c80d cppresttest!wmainCRTStartup+0x0000000d [f:\dd\vctools\crt\crtw32\startup\crt0.c @ 165]
77897c04 kernel32!BaseThreadInitThunk+0x00000024
77bcad1f ntdll!__RtlUserThreadStart+0x0000002f
77bcacea ntdll!_RtlUserThreadStart+0x0000001b


Dropbox crash dump quick analysis (on Windows)

I don’t exactly remember the last time I installed or upgrade the Dropbox on my Windows 8 laptop, but today one of my application started crashing itself whenever I opened a file open browser within app and it turned out it caused by Dropbox extension after quick analysis of crash dump. Unfortunately re-installing the most recent version doesn’t fix the problem so far.

Shows the moment when the crash occurred.

0:002> r
eax=59d0d000 ebx=74a91a9c ecx=00000000 edx=0000d0d0 esi=74a91aa0 edi=0000003f
eip=74ac7736 esp=0c04c434 ebp=0c04c440 iopl=0 nv up ei pl nz ac pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010216
74ac7736 0fb710 movzx edx,word ptr [eax] ds:002b:59d0d000=????  <== invalid memory access

Let’s see the call stack who gave the wrong param.

0:002> kP L4
ChildEBP RetAddr 
0c04c440 74abae83 msvcr90!wcspbrk(
 wchar_t * string = 0x59d0cf80 "C:\Users\\AppData\Roaming\Dropbox\shellext \new_trace탐탐", 
 wchar_t * control = 0x74a91a9c "?*")+0x34
0c04c8d8 59405f72 msvcr90!_wstat64i32(
 wchar_t * name = 0x59d0cf80 "C:\Users\\AppData\Roaming\Dropbox\shellext \new_trace탐탐", 
 struct _stat64i32 * buf = 0x0c04c8f8)+0x5d
WARNING: Stack unwind information not available. Following frames may be wrong.
0c04c940 59406524 DropboxExt_24+0x5f72
0c04cd58 594135ff DropboxExt_24+0x6524
DropboxExt_24 calls msvcr90!_wstat64i32 with 0x59d0cf80.
0:002> dU 0x59d0cf80 
59d0cf80 "C:\Users\\AppData\Roami"
59d0cfc0 "ng\Dropbox\shellext \new_trace탐탐"
59d0d000 "????????????????????????????????"
59d0d040 "????????????????????????????????"
59d0d080 "????????????????????????????????"
59d0d0c0 "????????????????????????????????"
59d0d100 "????????????????????????????????"
59d0d140 "????????????????????????????????"
59d0d180 "????????????????????????????????"
59d0d1c0 "????????????????????????????????"
59d0d200 "????????????????????????????????"
59d0d240 "????????????????????????????????"
0:002> r eax
The address 59d0d000 is invalid and inaccessible area. I turned on gflag while capturing this.
0:002> !gflag
Current NtGlobalFlag contents: 0x02000000
 hpa - Place heap allocations at ends of pages
So it could show the original heap size as follows:
0:002> !heap -p -a 0x59d0cf80
 address 59d0cf80 found in
 _DPH_HEAP_ROOT @ 59a81000
 in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
 59a8309c: 59d0cf80 7c - 59d0c000 2000
 0f578d9c verifier!AVrfDebugPageHeapAllocate+0x0000023c
 7726f819 ntdll!RtlDebugAllocateHeap+0x00000032
 772072db ntdll!RtlpAllocateHeap+0x00036e22
 771d06d3 ntdll!RtlAllocateHeap+0x0000014c
 74af3db8 msvcr90!malloc+0x00000079 [f:\dd\vctools\crt_bld\self_x86\crt\src\malloc.c @ 163]
 59405ecd DropboxExt_24+0x00005ecd
 59405ca4 DropboxExt_24+0x00005ca4
 59406513 DropboxExt_24+0x00006513
 594135ff DropboxExt_24!DllUnregisterServer+0x0000cb3f
 594136b9 DropboxExt_24!DllUnregisterServer+0x0000cbf9
 771d7aee ntdll!LdrxCallInitRoutine+0x00000016
 771d7a6f ntdll!LdrpCallInitRoutine+0x00000043
 771e07bc ntdll!LdrpInitializeNode+0x0000011d
 771e065e ntdll!LdrpInitializeGraph+0x00000059
 771dff22 ntdll!LdrpPrepareModuleForExecution+0x00000121
 771e0d88 ntdll!LdrpLoadDll+0x00000392
 771dc3ce ntdll!LdrLoadDll+0x00000067
 75a42551 KERNELBASE!LoadLibraryExW+0x000000c2
 75291892 combase!LoadLibraryWithLogging+0x0000001b [d:\blue_gdr\com\combase\common\loadfree.cxx @ 160]
 752917e0 combase!CClassCache::CDllPathEntry::LoadDll+0x0000003e [d:\blue_gdr\com\combase\objact\dllcache.cxx @ 2409]
 7529169a combase!CClassCache::CDllPathEntry::Create+0x00000035 [d:\blue_gdr\com\combase\objact\dllcache.cxx @ 2252]
 75290fe2 combase!CClassCache::CClassEntry::CreateDllClassEntry+0x000000f3 [d:\blue_gdr\com\combase\objact\dllcache.cxx @ 1048]
 752911a8 combase!CClassCache::GetClassObjectActivator+0x00000851 [d:\blue_gdr\com\combase\objact\dllcache.cxx @ 6042]
 7529015a combase!CClassCache::GetClassObject+0x00000030 [d:\blue_gdr\com\combase\objact\dllcache.cxx @ 5808]
 75290e4c combase!CServerContextActivator::CreateInstance+0x00000107 [d:\blue_gdr\com\combase\objact\actvator.cxx @ 999]
 7528d0f6 combase!ActivationPropertiesIn::DelegateCreateInstance+0x0000006e [d:\blue_gdr\com\combase\actprops\actprops.cxx @ 1906]
 75290d29 combase!CApartmentActivator::CreateInstance+0x00000075 [d:\blue_gdr\com\combase\objact\actvator.cxx @ 2323]
 75290c55 combase!CProcessActivator::CCICallback+0x00000039 [d:\blue_gdr\com\combase\objact\actvator.cxx @ 1786]
 7529095a combase!CProcessActivator::AttemptActivation+0x0000002c [d:\blue_gdr\com\combase\objact\actvator.cxx @ 1673]
 75290baa combase!CProcessActivator::ActivateByContext+0x00000094 [d:\blue_gdr\com\combase\objact\actvator.cxx @ 1539]
 75290c0c combase!CProcessActivator::CreateInstance+0x00000046 [d:\blue_gdr\com\combase\objact\actvator.cxx @ 1405]
 7528d0f6 combase!ActivationPropertiesIn::DelegateCreateInstance+0x0000006e [d:\blue_gdr\com\combase\actprops\actprops.cxx @ 1906]
The heap allocation callstack shows DropboxExt_24+0x00005ecd actually allocated only 0x7c. (UserSize is 0x7c), not area for whole path.
0:002> ? 0x7c 
Evaluate expression: 124 = 0000007c
0:002> lmvm DropboxExt_24
start end module name
59400000 59423000 DropboxExt_24 (export symbols) DropboxExt.24.dll
 Loaded symbol image file: DropboxExt.24.dll
 Image path: C:\Users\\AppData\Roaming\Dropbox\bin\DropboxExt.24.dll
 Image name: DropboxExt.24.dll
 Timestamp: Tue Jun 24 09:31:58 2014 (53A8C6FE)
 CheckSum: 00021746
 ImageSize: 00023000
 File version:
 Product version:
 File flags: 0 (Mask 3F)
 File OS: 4 Unknown Win32
 File type: 2.0 Dll
 File date: 00000000.00000000
 Translations: 0409.04e4
 CompanyName: Dropbox, Inc.
 ProductName: Dropbox
 InternalName: DropboxExt.dll
 OriginalFilename: DropboxExt.dll
 FileDescription: Dropbox Shell Extension
 LegalCopyright: (c) Dropbox, Inc. All rights reserved

Tips for debugging COM AddRef/Release leaks

In Windows environment, adding an accessibility support to a program means you’ll have to do a lot of COM coding. For example, IRawElementProviderSimple is the most fundamental interface you should implement for every provider. So at first I started developing providers with ATL and throughout the process I learned few tips I’d like to share here:

1. Add the ‘_ATL_DEBUG_INTERFACES’ macro


MSDN link:

One thing should remember. If you add the _ATL_DEBUG_INTERFACES to your project, then you cannot use ‘static_cast’ to get an interface pointer between interfaces you inherited and always should get it via QueryInterface. If not, the code will crash instantly. Please refer to following forum quote more details:

Before using _ATL_DEBUG_INTERFACES, the code did a risky "static_cast"
(which itself should be a crime!) to convert a interface pointer to the
coclass object pointer. It apparently worked fine with AddRef/Release and so
one. However, as soon as _ATL_DEBUG_INTERFACES is defined, the _QI_Thunk
interface goes in between and the simple single inheritance didn't work out
any more. Thus the attempt to AddRef caused first-chance access violations
because the address of the function call was invalid and the reference count
were less than expected since. After you released and released it again, you
got the crash.

The fix for this is never do such cast. If you definitely need to get the
pointer to the class object, use a hidden method or get property to return
the this pointer.


2. Use CAdapt to contain CComPtr in std::vector

Consider wrapping CComPtr instances with CAdapt in order to maintain CComPtr instances within std::vector to avoid & operator problem.

CAdapt MSDN Link:

Typically, you will use CAdapt when you want to store CComBSTR, CComPtr, CComQIPtr, or _com_ptr_t objects in a container-style class. This was most commonly necessary for C++ Standard Library containers prior to support for the C++11 Standard, but C++11 Standard Library containers automatically work with types that have overloaded operator&(). The Standard Library achieves this by internally usingstd::addressof() to get the true addresses of objects