1

I'm using VC++ 2015 to compile the following program.

#include <oleacc.h>
#include <unordered_map>

#pragma comment(lib,"User32.lib")
#pragma comment(lib,"Oleacc.lib")

thread_local std::unordered_map<int, int> something ;

int main( int argc, char* argv[] ){
    
    MessageBox(0, "Program started", "Test program", MB_SETFOREGROUND) ;
        
    IAccessible* test ;
    AccessibleObjectFromWindow(GetForegroundWindow(), OBJID_WINDOW, IID_IAccessible, (void**)&test) ;   
}

Command line:
cl test.cpp /EHsc /link /MACHINE:x86 /entry:mainCRTStartup /subsystem:windows,5.1

The program shows a message box and exits. It works fine on all Windows versions except Windows XP, in which nothing happens when the program icon is double-clicked.

There's no error message or any indication that the program failed. It just does nothing. It shows up in the task manager for a fraction of a second and then it disappears.

The following two elements must be present for the program to fail in Win XP.

  1. A thread_local unordered_map in the global scope.
  2. A call to AccessibleObjectFromWindow

If I make any of the following changes, the program does work in XP:

  • Changing unordered_map to std::map
  • Removing the thread_local keyword
  • Moving the thread_local variable inside main
  • Removing the call to AccessibleObjectFromWindow

Is there any command line parameter I can pass to the compiler/linker so that the program works in WinXP?


UPDATE:

If I add /MD to the command line (i.e. use the runtime installed in the OS), WinXP can run the program successfully.

This shows that the problem is some sort of incompatibility between Windows XP and the MSVC runtime library embedded into the executable by VS2015 (I also tried with VS2019, but made no difference).

I tried building a project through the GUI and selecting Windows XP (v140_xp) as the platform toolset, but the problem still occurs.

I guess my only option is to change unordered_map to map. Or to get rid of thread_local somehow.

Seth
  • 83
  • 7
  • 1
    You have not initialise COM. – Richard Critten Jul 02 '20 at 00:45
  • 1
    @RichardCritten, Initializing COM makes no difference since the `main` function is never called in the first place. – Seth Jul 02 '20 at 01:34
  • Does this answer your question? [How to target Windows XP in Microsoft Visual Studio C++](https://stackoverflow.com/questions/35664861/how-to-target-windows-xp-in-microsoft-visual-studio-c) – Simon Mourier Jul 02 '20 at 06:08

1 Answers1

0

Try adding /Zc:threadSafeInit- to the compiler command line.

From Thread-safe Local Static Initialization for VC++ 2015:

Thread-safe static local variables use thread-local storage (TLS) internally to provide efficient execution when the static has already been initialized. The implementation of this feature relies on Windows operating system support functions in Windows Vista and later operating systems. Windows XP, Windows Server 2003, and older operating systems do not have this support, so they do not get the efficiency advantage. These operating systems also have a lower limit on the number of TLS sections that can be loaded. Exceeding the TLS section limit can cause a crash. If this is a problem in your code, especially in code that must run on older operating systems, use /Zc:threadSafeInit- to disable the thread-safe initialization code.

dxiv
  • 16,984
  • 2
  • 27
  • 49