InterlockedIncrement64 with managed C++

2019-06-22 12:38发布

问题:

I'm porting code written under Visual Studio 2012 to compile with Visual Studio 2015. The code builds OK with Windows 2012.

I have an issue with some code that calls InterlockedIncrement64. It builds OK for an x64 target, but fails where the target is Win32 and the calling code is managed (i.e. compiled with /clr), yielding:

error C3861: 'InterlockedIncrement64': identifier not found

Looking in winnt.h, it seems that InterlockedIncrement64 is undefined when the target is Win32 and _MANAGED is defined.

I can rearrange the code such that InterlockedIncrement64 isn't called for managed code, but I'm still curious to know why this change in behavior has come with Visual Studio 2015.

回答1:

As the name implies, InterlockedIncrement64 is an atomic increment operation for a LONGLONG, and it needs memory to be 64 bit aligned.

Given that you can't set memory alignment in managed code and it may be used for managed class members then this limitation makes sense (to me): "...otherwise, this function will behave unpredictably on multiprocessor x86 systems and any non-x86 systems.". Think about this:

::InterlockedIncrement64(&_memberVariable);

If _memberVariable is allocated in managed world, then it won't be 64-bit aligned (though it may happen by chance), and this code will always fail for Win32. It's simpler to remove this function when _MANAGED is defined.

Workaround: check #ifdef _MANAGED and call Interlocked::Increment instead, or drop atomicity (!) but include a memory barrier after increment.