Visual C++ 2015 runtime broken on Windows Server 2003 (C++11 magic statics) - by Backbone1981

Status : 

  By Design<br /><br />
		The product team believes this item works according to its intended design.<br /><br />
		A more detailed explanation for the resolution of this particular item may have been provided in the comments section.


4
0
Sign in
to vote
ID 1789709 Comments
Status Closed Workarounds
Type Bug Repros 2
Opened 9/14/2015 8:15:06 AM
Access Restriction Public

Description

On Windows Server 2003 C++11 magic statics are broken when used in a project which uses a C# frontend, a C++ CLR wrapper and C++ native code. The application crashes with an access violation when checking for magic static initialization. It does not crash on Windows Server 2012 or Windows 7.

To me it looks like C++11 magic statics are implemented by using thread local store and that store is not correctly set up on Windows Server 2003 (__tls_index returns 0 into EAX).

Also see my question on stackoverflow: http://stackoverflow.com/questions/32517234/access-violation-on-static-initialization

See demo project and crash dump attached.

----------
Unhandled exception at 0x1000167E (Native.dll) in Managed.exe.dmp: 0xC0000005: Access violation reading location 0x00000000.
----------
class Singleton
{
public:
    Singleton()
    { }

    static Singleton* GetInstance()
    {
        static Singleton Instance; // !!! crashes here !!!
        return &Instance;
    }

}; // class Singleton
----------
    static Singleton* GetInstance()
    {
10001650  push        ebp  
10001651  mov         ebp,esp  
10001653  push        0FFFFFFFFh  
10001655  push        10006A8Ch  
1000165A  mov         eax,dword ptr fs:[00000000h]  
10001660  push        eax  
10001661  mov         eax,dword ptr ds:[1001B334h]  
10001666  xor         eax,ebp  
10001668  push        eax  
10001669  lea         eax,[ebp-0Ch]  
1000166C  mov         dword ptr fs:[00000000h],eax  
        static Singleton Instance;
10001672  mov         eax,dword ptr ds:[1001B5D0h]  // eax,dword ptr [__tls_index (0FBF0668h)] in debug build
10001677  mov         ecx,dword ptr fs:[2Ch]  
1000167E  mov         edx,dword ptr [ecx+eax*4] // !!! access violation here !!!
10001681  mov         eax,dword ptr ds:[1001B5A4h]  
10001686  cmp         eax,dword ptr [edx+4]  
1000168C  jle         Native::Singleton::GetInstance+79h (100016C9h)  
----------
EAX = 00000000 EBX = 00000000 ECX = 00000000 EDX = 006A0003 ESI = 001647C8
EDI = 0012F3BC EIP = 1000167E ESP = 0012F394 EBP = 0012F3A4 EFL = 00010282 

Sign in to post a comment.
Posted by Jonathan [MSFT] on 9/24/2015 at 1:19 PM
Thank you for this bug report.

Windows Server 2003 and Windows XP have problems with dynamically loading a DLL (via LoadLibrary) that uses thread-local storage, which is what thread-safe statics use internally to provide efficient execution when the static local has already been initialized. As these systems are out of support, it is extremely unlikely for a patch to be created for those systems to add this support as is present in Vista and newer OSes, and we are reluctant to penalize the performance on in-support OSes to provide this functionality to the old out-of-support ones.

To work around the issue you can use /Zc:threadSafeInit- to disable the thread-safe initialization code and this will avoid the thread-local variable. Of course by doing so the initialization code reverts back to the VS2013 mode and is not thread-safe, so this option is only viable if you don't rely on the thread-safety of local statics.

Jonathan Emmett
Developer - Visual C++
joemmett@microsoft.com
Posted by Jonathan [MSFT] on 9/24/2015 at 1:18 PM
Thank you for this bug report.

Windows Server 2003 and Windows XP have problems with dynamically loading a DLL (via LoadLibrary) that uses thread-local storage, which is what thread-safe statics use internally to provide efficient execution when the static local has already been initialized. As these systems are out of support, it is extremely unlikely for a patch to be created for those systems to add this support as is present in Vista and newer OSes, and we are reluctant to penalize the performance on in-support OSes to provide this functionality to the old out-of-support ones.

To work around the issue you can use /Zc:threadSafeInit- to disable the thread-safe initialization code and this will avoid the thread-local variable. Of course by doing so the initialization code reverts back to the VS2013 mode and is not thread-safe, so this option is only viable if you don't rely on the thread-safety of local statics.

Jonathan Emmett
Developer - Visual C++
joemmett@microsoft.com
Posted by Microsoft on 9/16/2015 at 4:06 PM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If you require immediate assistance with this issue, please contact product support at http://support.microsoft.com/oas/default.aspx?prid=15825.