Microsoft KB Archive/292752

{|
 * width="100%"|

PRB: New Definitions of InterlockedExchange and InterlockedCompareExchange Not Backward Compatible

 * }

Q292752

-

The information in this article applies to:


 * Microsoft Platform Software Development Kit (SDK)
 * Microsoft Visual Studio 6.0

-

SYMPTOMS
When you compile a program after you have installed the latest Platform SDK on your computer, and you call InterlockedExchange or InterlockedCompareExchange, you may receive the following error message:

main.c(13) : warning C4047: 'function' : 'long *' differs in levels of indirection from 'void ** '

CAUSE
The function prototypes have changed since Microsoft released Visual Studio 6.0. The function prototypes were as follows:

PVOID InterlockedExchange(PVOID *, PVOID); PVOID InterlockedCompareExchange(PVOID *, PVOID, PVOID); The function prototypes in the Platform SDK for Microsoft Windows 2000 are as follows:

LONG InterlockedExchange(LPLONG, LONG); LONG InterlockedCompareExchange(LPLONG, LONG, LONG);

RESOLUTION
If you want to exchange two pointers, use the InterlockedExchangePointer and InterlockedCompareExchangePointer functions. If you are exchanging two 32-bit values, continue to use InterlockedExchange and InterlockedCompareExchange, but do not typecast to PVOID.

MORE INFORMATION
InterlockedExchange and InterlockedCompareExchange were intended to exchange pointers. Many developers recognized that pointers and DWORDs are both 32 bits long and used these APIs to exchange DWORDs. To suppress compilation errors, the DWORDs must be typecast to PVOID.

The APIs did not strictly need to change to support 64-bit Windows. However, code that uses these APIs to exchange DWORDs can contain hidden problems. By typecasting a 32-bit DWORD to a 64-bit pointer, an application is unintentionally exchanging an extra 32 bits of data. The symptoms can be very confusing and the compiler cannot provide any assistance because the variable is explicitly typecast in the function call.

Microsoft's solution is to keep the parameters in the original APIs as 32-bit values, but use LONGs in the prototype. The resulting compiler errors draw the developer's attention to the problem. The APIs to exchange pointers are now InterlockedExchangePointer and InterlockedCompareExchangePointer.

The new function prototypes are not backward compatible with older Platform SDKs and Visual Studio 6.0. You should update the function calls as soon as is practical. However, you may need to temporarily support compilation with both the older and newer include files. If this is the case, you can use the following workaround to check whether the new prototypes exist and to replace calls to the InterlockedExchange functions with calls to the corresponding pointer functions.

#if defined(InterlockedExchangePointer) && !defined(_M_IA64) Note that this code exploits the fact that InterlockedExchangePointer is a preprocessor definition. This may not be true in future releases of the Platform SDK, so this workaround should not be used as a long term solution.
 * 1) pragma message(&quot;\nWARNING: Using old InterlockedExchange, InterlockedCompareExchange definitions.\n&quot;)
 * 2) define InterlockedCompareExchange(X,Y,Z) InterlockedCompareExchangePointer(X,Y,Z)
 * 3) define InterlockedExchange(X,Y) InterlockedExchangePointer(X,Y)
 * 4) endif

Additional query words:

Keywords : kbAPI kbKernBase kbSDKWin32 kbThread kbDSupport kbGrpDSKernBase

Issue type : kbprb

Technology : kbVSsearch kbWin32SDKSearch kbAudDeveloper kbSDKSearch kbVS600