0

The definition of mbstate_t has changed from:

typedef int mbstate_t;

to

typedef struct _Mbstatet
{ // state of a multibyte translation
    unsigned long _Wchar;
    unsigned short _Byte, _State;
} _Mbstatet;

typedef _Mbstatet mbstate_t;

This is not backwards compatible and seems to imply all components of a Windows desktop application will need recompiling with VS 2015 if I am to use VS 2015. Obviously "all" is too strong here, only components using mbstate_t are affected. However, that's still not a good situation.

Are we expected to recompile if we migrate to VS 2015? Am I missing something here which means this isn't an issue?

Given that this struct has changed I have bigger concerns that there may be other breaking changes between VS 2013 and 2015. Is there a list of these anywhere?

Note:

I've already asked this question on MSDN but my gut tells me more eyes will be on it on Stack Overflow: https://social.msdn.microsoft.com/Forums/vstudio/en-US/8e50f348-0b6d-442c-8a1e-b1b8a4288fbc/mbstatet-is-not-backwards-compatible-between-vs-2015-and-vs-2013?forum=vcgeneral#8e50f348-0b6d-442c-8a1e-b1b8a4288fbc

Andrew Parker
  • 1,425
  • 2
  • 20
  • 28
  • `mbstate_t` is an **internal** structure. If you are using it, you are Doing It Wrong™. Apart from that, every revision of the Microsoft Compiler comes with it's own version specific CRT implementation. If you want to upgrade to another version of Visual Studio, you'll have to recompile your code. – IInspectable Aug 12 '15 at 09:10
  • That's not correct. `mbstate_t` is part of a public API (and is not MS specific either). There are many wchar functions which use it. Take your pick but even the MSDN docs use it: https://msdn.microsoft.com/en-us/library/tt1kc7c1.aspx. It may well be the case that there are ways to do most things without explicity using mbstate_t but nonetheless it is public and this is a breaking change. I unfortunately have to concern myself with these small details (I work on an SDK rather than specific software). I'm concerned that there are other such changes lurking. – Andrew Parker Aug 12 '15 at 09:49
  • [mbstate_t](http://en.cppreference.com/w/cpp/string/multibyte/mbstate_t)'s **implementation** is unspecified. As such, it is similar to a `HANDLE`: While you are using those types, the internal representation is subject to change, and no guarantees are made. A `HANDLE` does hide its implementation. `mbstate_t`'s internals need to be exposed, since it is user-constructable. If your library code relies on it, you'll need to make sure, that `mbstate_t` is not exposed at the interface. – IInspectable Aug 12 '15 at 15:06
  • I understand what opaque types are. There's a difference between changing the internal usage of an opaque type versus changing the definition of an opaque type. This is equivalent to exposing a public function and changing it's internal implementation vs changing it's signature. The former is of no business to me, the latter breaks binary compatibility. N.B. There's no reason for MS to actually expose the internal representation of mbstate_t. There are ways of guaranteeing the object will have the correct size and be initialzed properly. See most implementations of pthread for example. – Andrew Parker Aug 13 '15 at 01:54
  • Also note that I have a reply from someone at MS that answers the actual question. I was disappointed to see this downvoted as IMO it's a valid question. – Andrew Parker Aug 13 '15 at 01:55
  • I suppose the question was downvoted, since *"Are we expected to recompile if we migrate to VS 2015?"* is trivially easy to answer, and not generally useful. In fact, I cannot see how you would migrate to a new development platform **without** recompiling on that new development platform. That would be an interpretation of *"migrating"* that I'm not familiar with. Irrespective of that, since you do have an answer, you may consider answering your own question. Occasionally votes on questions change, when there is an answer providing additional context. – IInspectable Aug 13 '15 at 10:40
  • If you by "reply from someone at MS" you mean the reply by Igor Tandetnik on the MSDN thread you linked, then you should know he's not a Microsoft employee. – Ross Ridge Aug 21 '15 at 08:58

2 Answers2

1

To answer the question. Yes, you are expected to recompile everything if you wish to update to newer versions of Visual Studio. MS reserve the right to change any part of toolchain and libraries. There are clear examples of C headers and C++ headers changing. Plenty of other things could change as well which would make binary compatibility between versions difficult or impossible.

Some discussion / opinion

In my mind it is not 100% obvious that you'd need to recompile everything when updating to a newer version of the toolchain. Forcing a user to recompile everything to update to a new toolchain can be quite burdensome. In large projects you may be dependent on a lot of 3rd party code which you have no way of recompiling. Many SDK expend a lot of energy in ensuring backwards compatibilty so that users don't have to do this.

Interestingly the linker makes no effort to disallow linking against libraries built with older versions of the toolchain. It doesn't even warn! This behaviour might imply that it's acceptable to link old libraries with new code.

Anyway, I could waffle about this all day. One thing I wanted to point out is that if you know what you're doing then it is possible to link binaries built with older versions of VS against newer versions. You have to be very clear about what declarations (effectively your header files) your code was built against and know that these declarations either haven't changed or they have changed in a way that doesn't cause runtime errors. You also have to be sure that the compiler hasn't changed the way it handles builtins/intrinsics etc. in a sufficient way to hurt you. For example, the use of a try/catch block with MSVC will cause code to be automatically generated to handle exceptions. This will lead to implicit calls to functions provided by the runtime libs. That could easily change version to version and you could be left with undefined symbols or unexpected behaviour.

Proceed with caution :)

Andrew Parker
  • 1,425
  • 2
  • 20
  • 28
1

It used to be that Visual C++ actually did try to maintain C runtime library backwards compatibility at the object file (and thus static library) level. Opaque types like mbstate_t might change their internal representation, but they wouldn't change their size. This allowed an object file compiled with older versions of the CRT headers to work when linked with a newer version of the CRT.

(Note that this doesn't apply when CRT objects are passed across DLL boundaries. Multiple CRTs in the same program, whether statically or dynamically linked, are not compatible.)

This mostly only applied to C code however. The Standard C++ Library was not backwards compatible at all, and there are actually linker checks to enforce this. (Though not if the out of date object files were compiled with Visual Studio 2008 or earlier.) Also the C++ ABI is subject to change between major releases, so potentially the layout of C++ objects can change.

However as you've noticed with Visual Studio 2015, the C runtime library is no longer backwards compatible. The CRT went through a major refactoring and many things changed. Most of it is no even longer part of Visual Studio, and instead is now a part of the Windows operating system. As you've also noticed, there's no error or warning when you to try to link older binaries with the new CRT. As the old CRT didn't include any version symbols in the compiled object files, so there's way it can know if they were compiled using the old CRT headers.

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112