The Future of Non-Static Data Member Initialization

The Future of Non-Static Data Member Initialization

Rate This
  • Comments 23

In Visual Studio 2013 we shipped an implementation of non-static data member initialization (hereby referred to as “NSDMI”), which is a feature that allows code such as the following:

class C { int n = 42; };

Here, n is a non-static member of the class, and it is initialized directly in its declaration, and not via a constructor.

Unfortunately, the code in our compiler (some of it written 30 years ago) for handling initialization suffers from many longstanding architectural limitations. This code was sufficient for C++03-style initialization, but NSDMI, a C++11 feature, caused it to exhibit these limitations as severe bugs. One of these bugs is described in the MSDN article about error C2797. List initialization inside a non-static data member initializer would have been silently converted into a function call, resulting in incorrect behavior. That is, if one writes:

#include <vector>

class S std::vector<int> v{ 1, 2 }; };

The compiler would have treated the code above as if the user had written:

#include <vector>

class S std::vector<int> v = std::vector<int>(1, 2); };

Instead of initializing the vector with two given elements, the Visual Studio 2013 RTM compiler initializes it with length one and a single element. We’ve received countless bug reports about this behavior in the past year. Furthermore, this is not the only issue that prevents initializer lists from functioning correctly.

We originally planned to fix this bug in an update to Visual Studio 2013, but from an engineering perspective, the right thing to do is to avoid another kludge and thoroughly address the handling of initialization. But overhauling compiler architecture is a massive task due to the amount of fundamental code that needs to be modified. We could not risk creating incompatibilities or large bug tails in an update, so a correct implementation of NSDMI could only be shipped in a major release.

Meanwhile, we still needed to address the steady stream of incoming feedback about bad code generation, so we made the hard decision of creating error C2797. This error guides users towards avoiding the issue and working around it by writing explicit constructions of inner lists, as the MSDN article suggests. The following code, for example, works as expected:

#include <vector>

class S std::vector<int> v = std::vector<int> {1, 2}; };

We are aware that the release notes for Visual Studio 2013 Update 3 did not include a notification about this new error. That was a mistake and we sincerely apologize for any confusion this has caused. However, C2797 will continue to be present in all future versions of Visual Studio 2013, so we recommend that you immediately make use of the provided workarounds. The architectural changes and fixes for initialization will be included in Visual Studio “14” RTM.

  • I am afraid I don't really agree with your decision to force customers to buy the new version of your product (Visual Studio “14”) in order to overcome bugs present in the current release from just 10 months ago.

  • Hi,

     this post really should have been published a day or so before Update 3 came out and all would have been good ;-)

    Anyway, make sure that VS14 is C++14 compliant and all is forgotten :-)

    Kind regards,

    Sven

  • I agree with Evgenii Golubev, this is pretty shoddy. I purchased 2012 only to find it broken, upgraded to 2013 to still find key features broken and the solution is another upgrade - still with key features missing or broken no doubt? I recall Herb promising a new dawn for C++ on Microsoft platforms but what we get is the same old feeble tools. The open source community is light-years ahead on quality and delivery on what should be your cornerstone product. Microsoft has deep pockets and its about time it got  the checkbook out and hired an army of top talent to get this house in order, really oh dear me.

  • Thanks for the explanation and the workaround! I totally agree that a hard error with a known workaround is better than silent bad code generation. Glad to hear it will finally be fixed in VC14.

  • VS 2013 is much slower and buggier than VS 2012. How about concentrating on increasing performance and stability and decoupling the C++ tool chain from the IDE so you can update it without forcing us to spend quite a bit of money updating the IDE?

    Microsoft also needs to get back to the idea that happy developers means more and better products. (Versus seeing dev tools as a potential profit center.)

  • Start a new compiler.  New team.  Using old, what was it, Lattice, as an excuse only shows how badly this needs to happen.

  • What!? You refuse to fix a serious bug and blame the age of the code base?

    Seriously, just start over with Clang.

  • Thanks for explaining and documenting this limitation. I can live with it even though I don't like it. I know how hard it is to deal with ancient codebases from my own experience. And I certainly agree on not kludging stuff on. May I suggest to graft the shiny new VS'14' initialization code (after release) back onto VS2013 in the form of a final service pack or whatever you may call a bugfix update? Face-palm deficiencies like the above should be addressed in a professional product, imho.

  • Dear Kangyuan Niu,

    You wrote about the code in your compiler: "This code was sufficient for C++03-style initialization". However, an important feature introduced by the C++03 standard was never fully implemented by Visual C++: value-initialization. Is there any chance that the next release of Visual C++ will finally fully support C++03-style value-initialization?

    See also:

    Bug ID 499606, "Presence of copy constructor breaks member class initialization", by Alex Vakulenko

    Bug ID 484295, "VC++ does not value-initialize members of derived classes without user-declared constructor", by Sylvester

    Bug ID 100744, "Value-initialization in new-expression", reported by Pavel back in 2005 (was removed from Connect!)

    My compiler test on value-initialization at Boost: svn.boost.org/.../boost_no_com_value_init.ipp

    Which can be used as follows: http://rextester.com/TFH63485

    Sorry to repeat myself. I asked the same question before, on 10 August, at blogs.msdn.com/.../visual-studio-14-ctp-2-available.aspx

  • Agreed. Support Visual Studio versions released within the last 2.5 years.  We have the same thing with Visual Studio 2012 having only minimal fixes for core functionality.  The VS 2012 updates added extra features we did not need.

    We reduced our footprint of tools, libraries, etc to only Tier 1 supported ones from MS for just this reason.  Tier 1 including compiler, linker, debugger, SQL Server, basic OS, network APIs and little else.   Tier 2 technologies are likely to be end of life, unsupported, or touch-released (release only to update the release date with little or no changes to the underling code base).  

  • Yes, please make this fix available to VS2013 as a final update. If breaking code is a concern - why not release it as a seperate Platform Toolset - thats what this mechanism is for, right!? Just make sure the stl is part of that toolset - then everyone is happy and it won't interfere with the original VS2013 compiler.

  • Everyone, thanks for voicing your opinions. Niels, I have responded to you in the other thread.

    Regarding a potential "final patch" for Visual Studio 2013 that fixes NSDMI: We cannot do that. To implement initialization correctly, we've had to make major architectural changes in the compiler and it would be impossible to back-port those changes.

    We also can't bring back the incorrect RTM behavior because we feel that providing this diagnostic is strictly better than letting users deal with a very puzzling silent bad code generation issue. The downside is that some previously working code will no longer compile, but the upside is that the compiler will now reject code that had a risk of behaving badly anyway.

  • Sorry, Kangyuan, but there is no technical reason you cannot patch Visual Studio 2010, 2012 and 2013. None. If it would break a developers code, then he doesn't update. It's that simple. The only reasons Microsoft won't do this (and decouple the compiler and Visual Studio version) is arrogance and greed.

    This kind of nonsense may work with Office and users who haven't dealt with this very attitude at their own jobs. But you are dealing with developers, most of whom have sat in meetings while pointy head managers and marketers decided features should be in the bullet list of the next upgrade.

    (Incidentally, throwing the same effort into clang and LLVM would be a boon to C++ developers everywhere.)

  • In my view Microsoft had plenty of time to fix their architecture. C++11 features have been in talks  for close to 10 years now. And Herb is the head of the committee. How could you not have forseen that? 10 years is plenty of time to get a new compiler project started to clean out the old gunk.

  • It's good to see such information published! Thanks for that.

    And again, we see how coupling the C++ compiler to the IDE as tightly as MS does is holding you back from speedily adopting properly working C++new features.

    You see, the *real* problem with stuff like this is not that I have to buy a new VS version (isn't everyone on MSDN subscription anyway) -- the real problem is that, to get a new and fixed compiler, I have to wait for the whole bloody IDE package to be available, including an oil tanker full of features that I never need.

Page 1 of 2 (23 items) 12