From b694ada29489728a6d6764a59d7bc8c659786f74 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Fri, 27 Jan 2023 12:37:17 +0100 Subject: [PATCH] Do not memset(0) POD types "POD" is the wrong type trait to determine if something can be safely zero-filled in order to achieve zero initialization. Consider a type like struct POD { int POD::*ptr; }; This is a POD; its value initialization needs to value initialize the member, and since it's a pointer, that's zero initialization, and that's setting the pointer to null. On Itanium, a null pointer to data member is not zero filled; it actually has the value -1u. Hence, zero-filling via memset(0) a POD object like the one above is erroneous. Unfortunately there is no type trait in C++ that we can use to know if a given datatype can be value initialized by zero-filling -- we can check for trivial constructability, but that's a necessary condition, not a sufficient one (POD above is also trivially constructible). The test is disabled on MSVC because of a compiler bug. Fixes #238 --- doc/container.qbk | 4 --- .../boost/container/detail/copy_move_algo.hpp | 3 --- test/vector_test.cpp | 25 +++++++++++++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index 591edd9..981a151 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1276,10 +1276,6 @@ member object and member function pointers) to be initializable using `std::mems Most platforms are compatible with this initialization, but in case this initialization is not desired the user can `#define BOOST_CONTAINER_MEMZEROED_POINTER_IS_NOT_ZERO` before including library headers. -If neither `BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_NOT_ZERO` nor -`BOOST_CONTAINER_MEMZEROED_POINTER_IS_NOT_ZERO` is defined [*Boost.Container] also considers POD -types to be value initializable via `std::memset` with value zero. - [endsect] [endsect] diff --git a/include/boost/container/detail/copy_move_algo.hpp b/include/boost/container/detail/copy_move_algo.hpp index a7d23a5..8729b30 100644 --- a/include/boost/container/detail/copy_move_algo.hpp +++ b/include/boost/container/detail/copy_move_algo.hpp @@ -296,9 +296,6 @@ struct is_memzero_initializable #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO) || dtl::is_floating_point::value #endif - #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO) && defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL) - || dtl::is_pod::value - #endif ); }; diff --git a/test/vector_test.cpp b/test/vector_test.cpp index 6057ab1..e72f62c 100644 --- a/test/vector_test.cpp +++ b/test/vector_test.cpp @@ -220,6 +220,12 @@ bool test_span_conversion() #endif //BOOST_VECTOR_TEST_HAS_SPAN +struct POD { int POD::*ptr; }; +BOOST_STATIC_ASSERT_MSG + ( boost::container::dtl::is_pod::value + , "POD test failed" + ); + int main() { { @@ -392,5 +398,24 @@ int main() ); } + //////////////////////////////////// + // POD types should not be 0-filled testing + //////////////////////////////////// +#if !defined(_MSC_VER) + // MSVC miscompiles value initialization of pointers to data members, + // https://developercommunity.visualstudio.com/t/Pointer-to-data-member-is-not-initialize/10238905 + { + typedef boost::container::vector cont; + const std::size_t size = 10; + cont a(size); + for(std::size_t i = 0; i != size; ++i) { + if (a[i].ptr != 0) { + std::cerr << "POD test failed" << std::endl; + return 1; + } + } + } +#endif + return 0; }