Opened 15 years ago
Closed 15 years ago
#1217 closed Bugs (fixed)
value_initialized leaves data uninitialized, when using MSVC
Reported by: | Niels Dekker | Owned by: | Fernando Cacciola |
---|---|---|---|
Milestone: | Boost 1.35.0 | Component: | None |
Version: | Boost 1.34.1 | Severity: | Problem |
Keywords: | Cc: |
Description
The data of an instance of boost::value_initialized<T> may not be initialized properly, when using Microsoft Visual C++. I already contacted Fernando Cacciola, the author of value_initialized, and we have developed a workaround, that I would like to propose.
The problem
There are two kinds of types, for which the issue is relevant, for different reasons:
When T is an aggregate class or struct that contains both POD and non-POD members, the constructor of value_initialized<T> will typically leave the POD members of T uninitialized, when using MSVC:
#include <boost/utility/value_init.hpp> struct A { std::string s; int i; }; boost::value_initialized<A> a; BOOST_CHECK( get(a).i == 0 ); // Will fail on MSVC!
This is caused by a compiler bug, reported by Pavel at the Microsoft Connect website, 7/28/2005, Feedback ID 100744, Value-initialization in new-expression The report was closed at 11/14/2006, and its status was set to "Closed (Won't Fix)". The bug appears relevant to all versions of MSVC, including the next one (MSVC 2008, code name "Orcas").
When T is an array of a POD type, MSVC 2005 provides an interesting warning, within the constructor of the base class of value_initialized<T>:
warning C4351: new behavior: elements of array 'T' will be default initialized.
This tells us that an older version of the compiler wouldn't properly initialize value_initialized<T>. And indeed the following check fails, when using the 2003 version of MSVC:
typedef int B[2]; boost::value_initialized<B> b; // MSVC 2005 warning C4351: new behavior! BOOST_CHECK( get(b)[1] == 0 ); // Fails on MSVC 2003 (BOOST_MSVC == 1310).
The proposed workaround
A new version of value_init.hpp is attached to this report, which includes a workaround for MSVC. Basically, when constructing value_initialized<T> it clears the bytes of T, just before constructing T itself. It does so by having the bytes of T stored in an instance of aligned_storage::type, and memsetting those bytes to zero before doing a placement new for type T, at the location of the bytes.
The workaround works well for MSVC, because for a built-in type, the value zero always has a bit pattern of only zero's, on any platform supported by this compiler, AFAIK.
Note that the workaround itself is a correct and standard compliant implementation of boost::value_initialized, but it may have a small performance penalty in comparison to the original version.
--
Niels Dekker
http://www.xs4all.nl/~nd/dekkerware
Scientific programmer at LKEB, Leiden University Medical Center
Attachments (1)
Change History (6)
by , 15 years ago
Attachment: | value_init_MSVC_workaround.hpp added |
---|
comment:1 by , 15 years ago
Owner: | set to |
---|
comment:2 by , 15 years ago
comment:3 by , 15 years ago
The Microsoft compiler bug regarding Value-initialization in new-expression was reported by Pavel Kuznetsov (MetaCommunications). I would like to have his full name added to value_init_MSVC_workaround.hpp (line 22).
comment:4 by , 15 years ago
I just committed the proposed workaround to the trunk: value_init.hpp - SVN revision 39157
See also the Boost Developers mailing list: {utility} Proposal MSVC workaround for value_initialized - Ticket #1217
comment:5 by , 15 years ago
Milestone: | To Be Determined → Boost 1.35.0 |
---|---|
Resolution: | → fixed |
Status: | new → closed |
Proposes new version of value_init.hpp