TYPE_ALIGNMENT(LARGE_INTEGER) incorrect when building against Win10 SDK

Viewed 1333

I am running into issues with this assertion in the Win 10 SDK for Winnt.h, when upgrading from Win8.1 a C file which #includes winnt.h:

C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um\winnt.h(2487,1): error C2118: negative subscript

#if defined(__cplusplus) && (_MSC_VER >= 1600)
static_assert(__alignof(LARGE_INTEGER) == 8, "Windows headers require the default packing option. Changing this can lead to memory corruption."
" This diagnostic can be disabled by building with WINDOWS_IGNORE_PACKING_MISMATCH defined.");
#elif _MSC_VER >= 1300
#pragma warning(push)
#pragma warning(disable: 4116)
C_ASSERT(TYPE_ALIGNMENT(LARGE_INTEGER) == 8);    <========= LN2487
#pragma warning(pop)
#endif
#endif

The error is simply telling me the CASSERT failed, but I have explicitly set /Zp8 and that made no difference.

So I hacked Winnt.h:

// Much of the Windows SDK assumes the default packing of structs.
#if !defined(WINDOWS_IGNORE_PACKING_MISMATCH) && !defined(__midl) && !defined(MIDL_PASS) && !defined(SORTPP_PASS) && !defined(RC_INVOKED)
#if defined(__cplusplus) && (_MSC_VER >= 1600)
static_assert(__alignof(LARGE_INTEGER) == 8, "Windows headers require the default packing option. Changing this can lead to memory corruption."
    " This diagnostic can be disabled by building with WINDOWS_IGNORE_PACKING_MISMATCH defined.");
#elif _MSC_VER >= 1300
#pragma warning(push)
#pragma warning(disable: 4116)
#pragma pack(show)
C_ASSERT(TYPE_ALIGNMENT(LARGE_INTEGER) == 8);
#pragma warning(pop)
#endif
#endif

Test code:

#pragma pack(show)
#include "LibraryHeader.h" //somehow includes Windows.h
#pragma pack(show)

Now I get result:

value of pragma pack(show) == 8
value of pragma pack(show) == 4
value of pragma pack(show) == 8

So it seems the mess of 3rd party headers we are using must be causing this. Which is weird because it worked against the 8.1 SDK, and because the header itself explcitly tells us we must have 8-byte packing/alignment set in the compiler.

I guess the question comes down to: is there any way the W10 SDK is causing this given no code has changed and it compiles against W8.1 SDK? Or, has it always been like this and the W8.1 SDK failed to check?

2 Answers

The section of Winnt.h posted in the question from Win 10 SDK is missing from the Win8.1 SDK, which implies the issue was always there but unreported.

Microsoft provide a way to disable this check, using the WINDOWS_IGNORE_PACKING_MISMATCH preprocessor definition.

For those interested, I verified in the library that it was indeed pushing/popping packing values for specific machine architectures. I couldn't tell why but that was as deep as I was willing to go!

I ran into this same issue with old C source code that compiled fine with Visual Studio 2017 and earlier but issued the same error with Visual Studio 2019 using the Windows 10 SDK.

My problem was a couple of projects in the solution had explicitly set the Struct Member Alignment compiler option to /Zp1 which resulted in the C_ASSERT failing with the somewhat opaque error of "negative subscript" from include file winnt.h.

This could also be caused by using a pack pragma prior to the include file winnt.h being included or processed by the Preprocessor. See Negative Subscript in winnt.h posted into the Visual Studio Developer Community by someone who was doing that.

I changed the option from /Zp1 to Default and the project compiled fine.

See also Static assertion failed with "Windows headers require the default packing option..." and see as well ERROR Windows headers require the default packing option on winnt.h

See also this Visual Studio Developer Community post, C2118 error with Windows Kits 10.0.18362.0 in winnt.h, which several posts mentioning this seems to be due to a change in the Windows 10 SDK beginning with 10.0.18362.0.

This probably means that some of my structs which depend on a /Zp1 with a byte member alignment are going to create data errors so I have to track those down and use #pragma pack(push, 1) and #pragma pack(pop) where appropriate.

I'm adding this answer in case someone else needs a reminder about this possibility.

screenshot of project Properties dialog showing the Struct Member Alignment C/C++ compiler option

Related