I've written a DLL that creates an ATL CString object. I compile it with Visual Studio 2015 using the "Visual Studio 2015 - Windows XP (v140_xp)" platform toolset. The DLL is loaded using LoadLibrary/GetProcAddress.
It crashes under Windows XP in CAtlStringMrg::GetInstance when allocating the string object. The same application works well on Windows Vista and later.
Here is the disassembly:
static IAtlStringMgr* GetInstance()
{
#pragma warning(push)
#pragma warning(disable: 4640)
static CWin32Heap strHeap( ::GetProcessHeap() );
1003B100 mov eax,dword ptr fs:[0000002Ch]
1003B106 mov ecx,dword ptr [__tls_index (101B46C8h)]
1003B10C push esi
*** This is the instruction that causes the crash. eax and ecx are zero. ***
1003B10D mov esi,dword ptr [eax+ecx*4]
As you can see the code references __tls_index, thus it uses thread local storage. dumpbin also shows a .tls section that is not present when I compile my project with the old Visual Studio 2013.
Thread local storage is not supported on Windows XP when a DLL is loaded dynamically. This explains why the code above crashes.
However, I could not figure out why thread local storage is used. I can't find __declspec(thread) anywhere in the ATL sources.
I'm looking for a fix/workaround (other than going back from VS2015 to VS2013).
The issue has already been reported to Microsoft, but they did not comment/fix it yet: https://connect.microsoft.com/VisualStudio/feedback/details/1635157/crash-in-catlstringmrg-getinstance-under-windows-xp