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)

value_init_MSVC_workaround.hpp (3.4 KB ) - added by Niels Dekker 15 years ago.
Proposes new version of value_init.hpp

Download all attachments as: .zip

Change History (6)

by Niels Dekker, 15 years ago

Proposes new version of value_init.hpp

comment:1 by Dave Abrahams, 15 years ago

Owner: set to Fernando Cacciola

comment:2 by Niels Dekker, 15 years ago

Oops, I forgot to do

  #include <new>

within value_init_MSVC_workaround.hpp (line 34)

comment:3 by Niels Dekker, 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 Niels Dekker, 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 Fernando Cacciola, 15 years ago

Milestone: To Be DeterminedBoost 1.35.0
Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.