Visual Studio 2015 libc is not backwards compatible - visual-studio-2013

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

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 :)

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.

Related

Visual Studio's /experimental:module conflicting with Vulkan's core.h causing syntax error - compilation failure

A little forward message: since I was limited to the number of tags I was able to use, I chose the tag visual-studio although this pertains to at least Visual Studio 2015 minimum which is less of a concern as this is focused more towards the use of Visual Studio 2017 or Visual Studio 2019 with the language version being set to either C++17 or C++20.
I have noticed a peculiar conflict between these versions of Visual Studio and Vulkan v1.1
If one is building a Vulkan based application and they happen to turn on the compiler flags: /std:c++latest and /experimental:module
Documentation found from here:
docs.microsoft/experimental-module
docs.microsoft/modules
and tries to compile and or link against the Vulkan library it fails due to a the aforementioned conflict.
There is a major failure that is coming from vulkan_core.h as some of their defined structures have a member that is named module which can be seen from their spec sheet: khronos/vulkan/specs/1.1-extensions...
In Vulkan's VkPipelineShaderStageCreateInfo structure they have it defined like this:
typedef struct VkPipelineShaderStageCreateInfo {
VkStructureType sType;
const void* pNext;
VkPipelineShaderStageCreateFlags flags;
VkShaderStageFlagBits stage;
VkShaderModule module;
const char* pName;
const VkSpecializationInfo* pSpecializationInfo;
} VkPipelineShaderStageCreateInfo;
which contains a VkShaderModule named module and this conflicts with Visual Studio's /experimental:module compiler flag since this enables module to become a keyword within the C++17 and or C++20 languages.
This feature is available in Visual Studio 2017 and Visual Studio 2019, I'm not 100% sure but I think it is also available in Visual Studio 2015 as I think this is when Microsoft introduced it.
There has been a brief topic, thread or discussion about this found here:
https://developercommunity.visualstudio.com/content/problem/556929/enabling-modules-causes-syntax-error-in-vulkan-cor.html They mention that it is being investigated but I don't see much more on this topic than what I've found.
I even tried to search here first to see if there was any mention of it, but my search results were fruitless. So I decided to post this question as more of an awareness and reference to other users as I think that this is an important issue to address since Vulkan is becoming a popular 3D Graphics and Compute API tool to use.
So to my question(s) regarding this issue:
Are there any followups other than what was mentioned?
Is there any work around other than disabling the Visual Studio compiler feature?
Where would the responsibility of taking care of this fall to: The Khronos Group or LunarG who are responsible for the Vulkan library, Microsoft as they are adding this feature to their compiler or would this be something that would concern the actual C++ Standard?
Also; is module going to be considered an actual key word within the C++ language from the standard or will this be a Microsoft specific thing?
Are other compilers such as gcc or Clang effected by this?
I had asked these series of questions to get an overall feedback from the community as a whole.
I would also like to see others contribute to this post adding links of other discussions, plans, and possible resolutions that pertain and or are related to this specific topic making this a reference page for all readers of the C++ community!
Are there any followups other than what was mentioned?
The public issue tracker of vulkan has a topic on it: https://github.com/KhronosGroup/Vulkan-Docs/issues/568
The resolution is that module is to become a contextual keyword so the compiler shouldn't give an error on it.
Is there any work around other than disabling the Visual Studio compiler feature?
You can edit the vulkan header, the name of the member field doesn't matter for correct operation.
Where would the responsibility of taking care of this fall to.
Microsoft needs to fix their compiler.
Also; is module going to be considered an actual key word within the C++ language from the standard or will this be a Microsoft specific thing?
It is going to be a contextual keyword.
Are other compilers such as gcc or Clang effected by this?
If they implement the contextual keyword correctly then they will not be affected.

Compiling Microsoft Keyboard Layout Samples

I'd like to build a keyboard layout that runs on Win7 and later without using MSKLC.
I downloaded the Keyboard Layout Samples, and although it says it requires VS2013 Preview and WDK8.1 Preview, it builds using VS2012 and WDK8 after changing the "Platform Toolset" property from "WindowsApplicationForDrivers8.1" to "WindowsApplicationForDrivers8.0".
But: Checking the kbdus.dll built with Dependency Viewer reveals that it imports quite a lot of stuff from kernel32.dlland from msvcr110.dll. This is in contrast to kbdus.dll from the Windows\system32 directory, which, as one might expect, does not import anything and exports one single function.
My first question: Is it an issues that the dll built imports from msvcr110.dll?
I guess it is, as Win7 does not include this dll. (Honestly, I'm wondering how this can be, because these are official Microsoft samples.)
Tweaking around with compiler and linker settings, I managed to get rid of imports from msvcr110.dll, but the dll built still imports a lot of stuff and is quite large (> 70kB), compared to the original kbdus.dll (7kB). It's the same with x86 and x64, Debug and Release builds. I'm looking for the /compileandlinkanddonothingfancy switch.
My second question: How can these dlls be built correctly?
(Note: I found this question, but it is about WDK7. That will be what I try next, if I don't get it with WDK8.0)
I think one should pass /noentry to the linker.

Runtime Issues While Mixing Libraries from Different Versions of Visual Studio

I have encountered an unexpected Access Error while running a project I've built using two different versions of Visual Studio. My general configuration is as follows:
LibA is a static lib, static runtime linkage, msvc 8.0
LibB is a static lib, static runtime linkage, msvc 9.0
My target project for integration is a msvc 9.0 COM dll, which statically links the above libraries
This project builds, but crashes up at runtime with an access violation in some STL code. The stack seems to indicate that I've passed through headers both versions (8 and 9) during a call into a stream insertion operator. I realize that this is a problem.
Somehow, this call:
ost << std::dec << port_; //(originating from an object in LibA)
...descends through the following stack trace:
std::basic_ostream::operator<<(...) (ostream:283, msvc 8.0 version <-- expected, since LibA was built with this version)
std::num_put::put(...) (xlocnum:888, msvc 8.0 version <-- expected, since LibA was built with this version)
std::num_put::do_put(...) (xlocnum:1158, msvc 9.0 version!! !##$!%! <-- not expected, since LibA was built with msvc 8.0)
std::ios_base::flags() (xiosbase:374, msvc 9.0 version <-- follows from above)
The access violation happens in std::ios_base::flags(). I suspect it is due to the mix of implementations in the call stack (although I am not sure).
My questions are.
1.) Is the likely cause of this access violation the mixing of msvc header implementations?
2.) Is there a way to prevent these implementations from mixing?
3.) Is there a better way to configure these three projects for integration (assuming moving LibA from msvc 8.0 is undesirable)?
I am aware of the ideas raised in this question and this one. Here I am most interested in this specific problem, and if there is some way to avoid it.
Any insights would be appreciated.
You can't use different STL implementation in the same project. This means even different versions from the same compiler. If your LibA has a function that accepts std::vector as an argument you are only allowed to pass vector object from STL that LibA was built with. This is why many C++ libraries expose only C API.
Either you change your API or you rebuild all your projects using the same compiler.
You are doing something that you shouldn't. You are in the world of undefined behavior. There is no point in trying to debug this particular crash. Even if you managed to make this line work you would get a new crash somewhere else.
There is no guarantee of library binary compatibility between major versions of MSVC. STL code is mostly template code that gets expanded into your code. So you're static libraries probably have incompatible chunks of STL code inside of them.
In general, this shouldn't be a problem, unless that STL code is part of the interface to the library. For example, if you pass iterators or a reference to a vector from one library to another, you're in trouble.
The best solution is to build everything with the same version of the compiler. If you can't do that (e.g., if the one of the libraries is from a third-party), you're probably stuck.

Which headers should I not use if I don't want my program to be linked with any of msvc*.dll's?

Which headers should I not use if I don't want my program to be linked with any of msvc*.dll ?
At the moment my application uses:
kernel32
user32
shell32
msvcp90
msvcr90
I want to get rid of the bottom two files. I don't mind if I will have to rewrite certain aspects of the program.
Because I know if you code in C and then link it won't link any msvc's
I believe you have to change the way the CRT is linked into your program. I think for that you have to change the C++->Code Generation->Runtime-Library to the static version. This is for Visual Studio 2005, don't know about newer versions.
Those libraries contain the C++ runtime - heap management and other stuff hard to get rid from.
You could link the C++ statically instead - use "C++ -> Code Generation -> Runtime Library" setting. Then you will not need those .dll files. However this is not the recommended way - if a vulnerability is found in the C++ runtime you'll have to recompile and reship your program.
Static link is the right answer. A related bit of advice is to use depends.exe to see what functions your exe is actually hitting in the dependent dlls. Those dependencies might be due to explicit use on your part or due to CRT implementation that you don't explicitly invoke.

Can I use a Visual Studio 6 compiled C++ static library in Visual Studio 2008?

Is it possible to use a C++ static library (.lib) compiled using Visual Studio 6 in Visual Studio 2008?
It really depends. Does the lib expose only 'extern "C"' functions where memory is either managed by straight Win32 methods (CoTaskMemAlloc, etc) or the caller never frees memory allocated by the callee or vice-versa? Do you only rely on basic libraries that haven't changed much since VS 6? If so, you should be fine.
There are 2 basic things to watch for. Changes to global variables used by 3rd-party libraries, and changes to the structure of structs, classes, etc defined by those 3rd-party libraries. For example, the CRT memory allocator has probably changed its hidden allocation management structures between the 2 versions, so having one version of the library allocate a piece of memory and having another free it will probably cause a crash.
As another example, if you expose C++ classes through the interface and they rely on MS runtime libraries like MFC, there's a chance that the class layout has changed between VS 6 and VS 2008. That means that accessing a member/field on the class could go to the wrong thing and cause unpredictable results. You're probably hosed if the .lib uses MFC in any capacity. MFC defines and internally uses tons of globals, and any access to MFC globals by the operations in the .lib could cause failures if the MFC infrastructure has changed in the hosting environment (it has changed a lot since VS 6, BTW).
I haven't explored exactly what changes were made in the MFC headers, but I've seen unpredictable behavior between MFC/ATL-based class binaries compiled in different VS versions.
On top of those issues, there's a risk for functions like strtok() that rely on static global variables defined in the run-time libraries. I'm not sure, but I'm concerned those static variables may not get initialized properly if you use a client expecting the single-threaded CRT on a thread created on the multi-threaded CRT. Look at the documentation for _beginthread() for more info.
I shouldn't think why not - as long as you keep the usual CRT memory boundaries (ie if you allocate memory inside a library function, always free it from inside the library - by calling a function in the lib to do the freeing).
this approach works fine for dlls compiled with all kinds of compilers, statically linked libs should be ok too.
Yes. There should be no issues with this at all. As gbjbaanb mentioned, you need to mind your memory, but VS2008 will still work with it. As long as you are not trying to mix CLR, (managed) code with it. I'd recommend against that if at all possible. But, if you are talking about raw C or C++ code, sure, it'll work.
What exactly are you planning on using? (What is in this library?) Have you tried it already, but are having issues, or are you just checking before you waste a bunch of time trying to get something to work that just wont?
Sure it'll work.
Are you asking where in VS2008 to code the references?
If so, go to proj props -> Linker -> Input on Configuration properties on the property pages. Look for "additional dependencies" and code the .LIB there.
Go to proj props -> Linker -> General and code the libs path in "Additional Library Directories".
That should do it!!
There are cases were the answer is no, when we moved from VS6 to VS2k5 we had to rebuild all our libraries, as the memory model had changed, and the CRT functions where different.
There were a handful of breaking changes between VC6, VS2003, VS2005 and VS2008. Visual C++ (in VS2005) stopped support for single-threaded, statically linked CRT library. Some breaking changes enumerated here and here. Those changes will impact your use of VC6 built libs in later versions.

Resources