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’ (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!
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 —————————
For information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts.
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]
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
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 –
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]
_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.
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.
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
0c04c440 74abae83 msvcr90!wcspbrk(
wchar_t * string = 0x59d0cf80 "C:\Users\xxxxx.xxx\AppData\Roaming\Dropbox\shellext \new_trace탐탐",
wchar_t * control = 0x74a91a9c "?*")+0x34
0c04c8d8 59405f72 msvcr90!_wstat64i32(
wchar_t * name = 0x59d0cf80 "C:\Users\xxxxx.xxx\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.
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:
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.
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