boost::aligned_storage broken on VC12 for alignment values of 8
Very surprising, but easily reproducible with VC12 (2013), Release or
Debug configuration, Win32 platform: the following program will often*
throw:
#include
On 30/03/14 08:41, Glen Fernandes wrote:
Very surprising, but easily reproducible with VC12 (2013), Release or Debug configuration, Win32 platform: the following program will often* throw:
#include
#include <cstdint> int main() { boost::aligned_storage<8, 8>::type a; if (((std::uintptr_t)&a % 8) != 0) { throw 1; } } * Four of every five times it failed because the storage was only 4-byte aligned, not 8-byte aligned.
Does not reproduce for x64 builds, just x86 builds. Does not reproduce with alignment values other than 8.
AFAIK, with Windows 32-bit, you cannot reliably have an object with alignment greater than 4 on the stack. Use dynamic memory allocation.
On Sun, Mar 30, 2014 at 9:22 AM, Mathias Gaunard wrote:
AFAIK, with Windows 32-bit, you cannot reliably have an object with alignment greater than 4 on the stack.
I have seen that VC has notoriously strange alignment and layout rules for 32-bit code. I wonder if that should inhibit making boost::aligned_storage<..., N>::type at least as reliable as VC12's std::aligned_storage<..., N>::type or __declspec(align(8)), both of which seem to work correctly. Glen
AFAIK, with Windows 32-bit, you cannot reliably have an object with alignment greater than 4 on the stack.
I have seen that VC has notoriously strange alignment and layout rules for 32-bit code. I wonder if that should inhibit making boost::aligned_storage<..., N>::type at least as reliable as VC12's std::aligned_storage<..., N>::type or __declspec(align(8)), both of which seem to work correctly.
Sorry to be so late in coming to this: this is both nasty but also apparently unfixable, on the one hand, VC++ basically lies about the alignment of some types: int main(int argc, _TCHAR* argv[]) { typedef long long align_t; std::cout << __alignof(align_t) << std::endl; assert(__alignof(align_t) % 8 == 0); // OK align_t a; assert(((std::uintptr_t)&a % 8) == 0); // OK char c = 0; align_t a1; assert(((std::uintptr_t)&a1 % 8) == 0); // Fails return 0; } BTW this is true also of std::aligned_storage which also fails the final assert above. If instead we had: typedef __declspec(align(8)) struct some_struct_type align_t; Then the asserts all pass, but now align_t can not be passed through a function call by value. In fact this was a previous bug in the type traits lib: http://article.gmane.org/gmane.comp.lib.boost.devel/173011 So we're basically screwed whatever we do. Regards, John.
On Thu, Apr 24, 2014 at 5:22 AM, John Maddock wrote:
Sorry to be so late in coming to this: this is both nasty but also apparently unfixable, on the one hand, VC++ basically lies about the alignment of some types: [snip]
BTW this is true also of std::aligned_storage which also fails the final assert above. If instead we had:
typedef __declspec(align(8)) struct some_struct_type align_t;
Then the asserts all pass, but now align_t can not be passed through a function call by value. In fact this was a previous bug in the type traits lib: http://article.gmane.org/gmane.comp.lib.boost.devel/173011
So we're basically screwed whatever we do.
*Nod*, I discovered shortly after that std::aligned_storage in VC was similarly affected. Whle I expected __declspec(align(N)) to be at least reliable (after a light test) that also is disappointgly not the case for the reasons you've indicated. Looks like MSVC-32 users should rely only upon Boost.Align's align() or aligned_alloc() for alignment values of 8. :) Glen
BTW this is true also of std::aligned_storage which also fails the final assert above. If instead we had:
typedef __declspec(align(8)) struct some_struct_type align_t;
Then the asserts all pass, but now align_t can not be passed through a function call by value. In fact this was a previous bug in the type traits lib: http://article.gmane.org/gmane.comp.lib.boost.devel/173011
So we're basically screwed whatever we do.
*Nod*, I discovered shortly after that std::aligned_storage in VC was similarly affected. Whle I expected __declspec(align(N)) to be at least reliable (after a light test) that also is disappointgly not the case for the reasons you've indicated.
I've just updated the type_traits docs to reflect these issues. Cheers, John.
[John Maddock]
If instead we had: typedef __declspec(align(8)) struct some_struct_type align_t; Then the asserts all pass, but now align_t can not be passed through a function call by value.
I filed DevDiv#874311 "alignas by-value parameters should be permitted" back in December. The compiler back-end team is aware that I need this for C++11 conformance. STL
If instead we had: typedef __declspec(align(8)) struct some_struct_type align_t; Then the asserts all pass, but now align_t can not be passed through a function call by value.
I filed DevDiv#874311 "alignas by-value parameters should be permitted" back in December. The compiler back-end team is aware that I need this for C++11 conformance.
That's great, thanks! John.
participants (4)
-
Glen Fernandes
-
John Maddock
-
Mathias Gaunard
-
Stephan T. Lavavej