Why is Microsoft’s C++ support so messy?
Microsoft has probably the best IDE in the world. It’s called Visual Studio, and lately it has been messed up with unnecessary ALL CAPS menu entries and the ugliest colors possible, not to mention that awful flat look. Besides that, Visual Studio is still the best IDE around.
For C#. It’s almost inconceivable to think about .NET development without the great support of Visual C#. It is possible, but it shouldn’t be done.
For C++ it’s another story. Microsoft has a long history with C++; in about 20 years you’d think they had the time to polish the C++ integration. They didn’t. I shall explain using two issues.
The runtime issues
Writing a program in C++, you can no longer just deliver your executable file. You also have to deliver the runtime you built against. And make no mistake, if you built with VS2008 or you build VS2008 SP1 it makes a huge difference, you have to deliver different runtime versions.
It’s not very easy to identify which runtime version you have to deliver. But the worst thing is: you don’t really understand why. Why are there so many runtime versions? Why aren’t they delivered with the operating system? What the heck do they deliver in 3GB and in the ton of service packs?
On my machine I have currently 10 runtime versions.
From these 10, two are for VC++ 2005, 4 are for for 2008 (with two more with a different architecture) and two different are for 2010 for different architectures. This happened probably because I have 10 different applications written in C++ installed. This is not ok.
<story real=”true”>So if you write a TicTacToe and you want to send it to your relatives to see your first TicTacToe and play it, you’ll have to ask them to install the proper runtime version. Which you don’t really know which it is; and you’ll end up asking them to install the same Visual Studio version as you.</story>
The handling of DLLs in general
It’s not just the runtime. It’s the whole DLL handling that is a problem here. With C#, you just add a DLL to the references and voila, it works. C++ is different; you need a DLL, which contains the code, and you need header files (which are equivalent to the metadata from the DLL). The problem is more complicated when it comes to C++:
- In DLL exported functions and classes and variables are identified by their name. For C++ we need name mangling, in which the name of the function also will contain the class name, as well as the parameter types or an encryption of the parameter types. There is no standard way of doing this.
- Standard Template Library is not as standard as you’d think and cannot be delivered as binary code. For the time being, no compiler was able to create a way to deliver C++ template code in an efficient manner. Moreover, the STL is delivered as header files and most of the functions will be inlined. It’s part of why the STL is so efficient. But that means that you can’t refer these types in the exported functions, because the headers might be different from version to version. The size of a string might be different from the size of the string you returned from your DLL.
- Different compilation options might give you different data structures, with different sizes, different packing and different alignment in memory. This is not an issue to be taken lightly.
Most of the library implementers expose a C-compatible interface. C is simpler; all symbols names are exactly the function names, there are no classes and no complex types. They return a pointer, because a pointer has a fixed size, and parameters are passed as pointers as well, because it’s simpler that way. But C++ library implementation is a game of avoiding all these issues.
And Microsoft chose to make it more complicated. In order to link against a DLL, you have to link against a static library, delivered as a .lib file. You’ll have to copy the DLL manually in the debug folder, because you don’t really want to install the DLL in the Windows folder. And you don’t want to install the DLL in the Windows folder because God knows how many other applications will require that DLL, and you’ll mess up those application with your version. This is how DLL hell was born, but this didn’t change. At all.
Is it possible to have this changed? On Linux things are a lot easier. There was only one name mangling scheme change, between GCC 2.9x and GCC 3.x, that made shared objects incompatible. This change is big enough, and was not seen in the Microsoft universe (where things stay ABI compatible for a long long time). To support this, you only had to have two shared objects, one for 2.9x and one for 3.x. The linking was done against, say libstdc++.so.2 which was a symlink to the proper implementation of the 2.9x ABI. Applications that used the new ABI just linked against libstdc++.so.3, symlink to the current 3.x ABI, which makes sense.
Moreover, to develop you only need the header files in addition to the shared object. No static library that you also need.
Things are a lot simpler on UNIX-like systems. And Microsoft hasn’t made much to alleviate these issues. If you don’t believe me try writing a program in C++ using SDL, with Microsoft’s Visual Studio Desktop Express Edition.
So, although Microsoft has done some things to improve C++ support in VS2012, it’s still far from being a friendly developer environment. I never felt as comfortable with C++ as in Linux distributions, and probably never will, by the way things are going.
And most of Microsoft Windows IS C++. Strange.