"Side By Side Assemblies" Bring DLL Hell 2.0
neutrino38 writes "This is an alert for all developers using Microsoft Visual Studio 2005. At the beginning of January, Microsoft issued a security fix for Visual Studio 2005 forcing the use of new dynamic libraries (DLLs) by all applications compiled with this IDE. Basically, applications compiled with Visual Studio 2005 will not work anymore on an ordinary (non-dev) PC unless the newer DLLs are installed. And we found out that this is true on fully updated PCs. I just posted some details and some suggested fixes." Read below for some more background on Microsoft's so-called "side by side assemblies."
For those unfamiliar with the Microsoft world, native microsoft applications written in C++ rely on dynamic libraries. Two of them are infamous: MSVCRT.DLL and MFCxx.dll. Because of software evolution and security fixes, multiple versions of these DLLs were often present in the system, causing application instability. Where Linux implemented a simple suffix notation on the dynamic libraries, Microsoft created a new beast in 2001: the Side By Side assembly. These are basically DLLs with a companion XML file that identifies them. The XML file contains a digital signature and when the system binds these DLLs dynamically to an application, it checks that the signature of the DLL matches the DLL itself. When everythings runs well, this is pretty transparent. But when issues arise, it becomes excruciatingly difficult to troubleshoot and fix. DLL hell is not over.
For those unfamiliar with the Microsoft world, native microsoft applications written in C++ rely on dynamic libraries. Two of them are infamous: MSVCRT.DLL and MFCxx.dll. Because of software evolution and security fixes, multiple versions of these DLLs were often present in the system, causing application instability. Where Linux implemented a simple suffix notation on the dynamic libraries, Microsoft created a new beast in 2001: the Side By Side assembly. These are basically DLLs with a companion XML file that identifies them. The XML file contains a digital signature and when the system binds these DLLs dynamically to an application, it checks that the signature of the DLL matches the DLL itself. When everythings runs well, this is pretty transparent. But when issues arise, it becomes excruciatingly difficult to troubleshoot and fix. DLL hell is not over.
Microsoft FTL.
What might be interesting to note here is that the summary isn't everything there is to side-by-side (SxS) assemblies.
Suppose you're building an application using two DLLs, let's call them A and B. Both depend on a third DLL named C. Now, suppose A uses C version X, and B uses C version Y. You're screwed, right? Not with SxS, since that allows multiple versions of C to be loaded. That's the real added value of SxS.
All this is in theory of course, which as we all know is in theory equal to practice, but in practice is not...
Error: password can't contain reverse spelling of ancient Chinese emperor
Speaking as a user, can we get statically linked libraries? I don't care if it's dependency hell or DLL hell. I want self-contained applications.
Instead of referencing the .dll in \Windows\System\ why don't you reference a copy of the .dll in \Program Files\Your Stupid App\ ?
Seems like a simple fix to me, though I'll admit most of my .dll experience comes from the asp.net/c# world.
Someone with knowledge of .NET internals care to comment?
It's NOT me! It's the meds! I'm on 1000mg of Fukitol.
That defeats the whole purpose of a DLL anyway. The thought was that you wouldn't have to "reinvent the wheel" and you could reuse code. However, Microsoft's failure to document their operating system's API thoroughly in a public manner led to developers relying on undocumented features that were later changed. Then, those applications needed older versions of those libraries and would install them over the newer versions. This, of course, crashed the newer applications. Ugh.
Everybody who developes applications for the Windows platform should know that you need to include the merge module for the C/C++ runtime libraries in your installer. You've just been luck so far that other applications have installed the DLL's you needed for you. Try your app the way it is on a clean install of Windows XP without the service packs and see how well that goes :P
In fact the SxS assembly system in windows is the only real way out of DLL hell, much better than the versioning scheme for shared libraries used in Linux. Get your facts straight before posting.
The interactive way to Go -- http://www.playgo.to/iwtg/en/
I upgraded my Fallout 3 installation yesterday. After patching, the game wouldn't run, returning some fairly obtuse message about import ordinals. So I googled the message, and found out it's because the game now links against a newer version of "Microsoft(R) Games for Windows(TM) Live(TM)" whatever. Note that this wasn't some new patch, it's months old and yet this problem, which must realistically be hitting quite a few users, persists. This isn't something you get via Windows Update either, this is just some obscure 'distributable runtime' crap you should know you need?
So let me repeat that: Super mainstream game on a super mainstream platform (Vista x64), no add-ons, I patch to the latest version and it won't start, nothing is mentioned at the developer's site.
Now I recognize good old Bethesda again. Here's how they'd be able to repro: Fully updated Vista machine, install game from DVD, apply patch, notice it won't fucking run.
I don't normally give much for the 'PC-gaming sucks' choir, but c'mon..
Belief is the currency of delusion.
This has been heavily debated in comments in the Visual C++ blog:
http://blogs.msdn.com/vcblog/archive/2009/08/05/active-template-library-atl-security-updates.aspx
Unfortunately, the VC++ team doesn't seem to understand what's wrong with pushing out a critical update through automatic updates that silently updates dependency requirements. I've personally seen projects that were suddenly broken by this update and the ensuing confusion that resulted.
Java?
Now that memory is so cheap and disk space even cheaper, do we still need the small process sizes that dynamic linking brings?
Would it be worth burning more RAM (although in an on-demand paged system, there's obviously no need to have your entire processl resident) to get rid of the problems associated with incompatible versions of libraries. Just go back to statically linking everything, so yo only ever need 1 binary - as all the routines it will ever call are already part of it.
politicians are like babies' nappies: they should both be changed regularly and for the same reasons
No, because that's what sxs solves. You can have multiple versions of the MSVCxxx libraries installed and each app can find the correct one.
It's similar to the library versioning that unix does, except instead of changing the filename each library has a manifest containing its version number and a checksum of the library, and the loader knows how to fing the right one.
This is a complete non-story written by someone who doesn't test applications on a clean system prior to distribution, then wonders why it doesn't work.
YHBT... anyhow, on OS X you can have multiple versions within a framework, and frameworks private to an application. So "it just works."
Packages work beautifully. Anything I need for my app can be bundled right along with it, or in any of the standard directories.
Multiple versions per framework is essentially how sxs works.. it's the same idea.
Private frameworks to an application isn't new - you can put DLLs local to a windows app too if you want.. OSX has a global frameworks directory that is similar to the sxs directory, and has the same problems eg. if you're linking to the itunes lib you have to check the one you're writing with is on the target system in the package installer (or install it, but for something like itunes that's probably a bad idea).
Yeah SxS works a treat. No more dll hell. Great for servicing too. The problem here is moronic devs not shipping the libraries that they link against. MS would be castigated if they didn't fix security holes. Why oh why does kdawson think this is a return to dll hell? Does he actually know what SxS is? Does he even have experience of windows development?
Writing "managed" code has nothing to do with using sane concurrency abstractions. You can do one without the other. Hell, you can easily write buggy managed code that relies on raw semaphores and deadlocks often, and you can write elegant message-passing C++ code. The key is the abstraction, not the runtime mechanism.
Brainfuck actually.
Everyone (even Windows programmers) should read Ulrich Drepper's piece on how to write shared libraries. (Warning: PDF.) (Likewise, even free software developers should read Raymond Chen's blog.)
everyone having their own DLL would be the same as just statically linking everything. you'd have tons of code duplicated and loaded. have no easy way to patch common code system wide.
People suffer DLL hell because it is better than not using DLLs at all.
“Common sense is not so common.” — Voltaire
Oh jesus christ I can't stand how fucking idiotic everything in this discussion is.
What happened: In August, they released a patch to the IDE that required a new version of the shared libraries. Binaries built with this patched version of the IDE/compiler/toolchain will by default require a version of DLLs that aren't installed by default on many systems.
What would have prevented this asshat's blog post: Write a fucking installer that includes the DLLs you use. Thus, when your compiler changes, and your new packages rely on some stuff, magically that 'some stuff' is bundled along with your binary, and everything _still works_. Relying on OTHER packages to have good installers that properly put stuff in to SxS is just idiotic. "Wah, I rely on stuff that I'm specifically told I can't rely on, Microsoft sucks, and SxS is evil!"
No. SxS has been SAVING your ass from updates like this since Windows XP. Surprisingly, you can now NOT recompile your project, and have it still work, even though there's a newer version of DLLs you depend on, because the backwards compatibility problem of these DLLs is just gone. The version YOU want and need and depend on is still there, still usable. Something else on the system that wants the newer version gets it, and all its patched glory. This is actually a security hole, and in THAT case, the DLL you depend on WILL change to fix the security problem. Nothing in the August 2009 update to VS 2005 seems to indicate that this happened, it's only for newly compiled binaries.
So, in summary: The blog poster is an idiot, he hates his user, he's too lazy to write a real installer, he has incompetent developers that don't care about the security of their product, and he asked for help and got 4 completely idiotic responses. Now everyone on slashdot who knows nothing about SxS and the actual problems it causes (and yes there are some) think that it's the same problem we've always had, but worse.
Note: I'm not a Windows developer (Linux developer), and I've not used Windows in well over a year (Mac user). But I've been bitten by SxS in my last job and dealing with VB.Net, back when I didn't know I had to make a real installer for my stuff. I somehow managed to learn to not be an idiot, and the blog poster should too.
If your installer doesn't make sure that is the case, you're an idiot, cause that's what installers are for.
I'm Rocco. I'm the +5 Funny man.
Neither is Microsoft Visual Studio 2005.
Oops. Correct link. (I wish Slashdot would warn about obviously incorrect links.)
This can bite you in a lot of conditions. One of the canonical examples is memory allocation. For example, foo.dll allocates memory and passes the pointer to bar.exe. To operate safely, bar.exe has to pass the pointer back to foo.dll so it can be freed. Otherwise, foo.dll might be using -- say -- malloc() and free() from one version of the C runtime library, and bar.exe might be using malloc() and free() from a different version. Because the different DLLs will end up allocating from different arenas, you'll corrupt both if you malloc() using one and free() using the other.
There's a reasonable argument that passing memory ownership without providing allocation functions is a bad way to design libraries. Unfortunately, some interface standards specify bindings that forbid providing that kind of deallocation function in the DLL. (I'm looking at you, CCSDS SLE! I still haven't forgiven you for inflicting this form of DLL hell upon me so many years ago.)
not having programmed for Windows for many years now what happens when these different versions of library C use different data structures or global variables?
Sometimes it is a good thing to use your own DLLs. I'm writing a mod tool for a game at the moment, and I am using Qt4 to provide the graphics. Qt4 on Windows by default is compiled with MinGW, but I compiled mine with Visual Studio. If I had the Qt4 DLLs in the system directory, it probably would cause issues for any other Qt4 using program that might use those particular DLLs. To be on the safe side, I kept the DLLs in the directory of the program.
SSC
This particular issue is C++ only, but that's simply because MS has screwed the way things used to work for unmanaged binaries.
You may still get this issue next time MS issues a patched version of any of the .NET libraries, imagine that your code will only run on .NET 3.5 SP1 patch 1234, then you'll see the exact same problem. I guess we're all used to installing all manner of .NET framework libs through WU so no-one sees this issue so far, but its only a matter of time.
Of course, if binaries used the previous version if the later one was not installed, things would be ok, but that's not the way they're doing things now.
Blood?
She made the willows dance
But when issues arise, it becomes excruciatingly difficult to troubleshoot and fix.
The version information is written in plain text in the manifest. The files have names based on the version information in the WinSxS folder. If you get the error and notice the files aren't there, its fairly trivial to troubleshoot and fix.
I'm not a fan of side by side assemblies, I just hate to see issues like this blown out of proportion as it obscures some of the real issues that developers face when developing for Windows (such as just about every bug filed on Microsoft Connect being closed as "by design" instead of being worked on or at the very least closed as "can't fix, compatibility issues", for example).
I hate to break it to you, but there is quite a lot of this going on. For instance, if you were to look at the source code of every app that needs to decode png files (just as example), you would probably find only about 50% use the libraries that come with the OS, and the reasons why vary:
* avoiding dll hell (as mentioned)
* the app is cross platform
* poor implementation of official dlls
* politics (at one stage Microsoft made tied certain dlls to the installation of IE, even though they had nothing to do with browser functionality)
Microsoft did this intentionally. They deprecated the vulnerable version of the dll. You "solution" to the problem of your customers still running the vulnerable version of the VC dlls should be to either force them to upgrade or install the new dlls for them. Instead you decide the security is a hassle and undo the fix on your developer machine, so you can ignore the larger issue that you are building insecure software and you customers are running insecure computers. Fix the problem, instead of whining about it and continuing to crank out crappy .net software. How hard would it be to have your software check for the problem dll versions, and direct the customer to download/install the new version? Cripes, games do it all the time when they check what version of direct x is installed.
Its as though any developer who doesn't work directly for Microsoft is an enemy of the state (Of Microsoft).
Python: 'And then suddenly you have a language which says "we're all stuck with whatever the whiniest coder wants".'
Whether or not that's true, either way this is a non-story. The point is that the OS makers already address this exact situation with technology X, and since he's not using technology X he has a program that no longer runs. That's not Microsoft's fault any more than it would be Linus' fault if his buggy application ran on Linux.
Comment of the year
First off, why on earth is the developer still using Visual Studio 2005? We're on Visual Studio 2008, SP1. That, right there, raises a red flag. If someone compiled something with an ancient version of gcc and found out it didn't work, when distributed, on more up to date Linux distributions, wouldn't you think that the appropriate response would be for our man to get his tools straightened out first?
I would think that if the author shipped his system with a copy of the runtimes and had them install in his application directory, he would have no problem at all. The Windows DLL load order is application directory first, then, some other stuff, so his application should always have the right libraries, if he shipped them. In fact, I even think there's some sort of a doohickey that you can do to have Windows look for COM components first in your own directory before it looks for them in common areas. There's no need to have "DLL hell" at all, unless the developer really asks for it.
Frankly, I doubt DLLs of the relatively small size of the CRT should even be used any more across different applications from different vendors.
1. First, you cannot possibly test your application with all the different versions and patch versions of DLLs that are out there, because patch releases now are way too fast. Reliability, right now, not performance, is the pre-eminent problem in the software community.
2. The static linker is now actually capable of removing unused code, from an image, it could not do that before.
3. DLLs have to be relocated when an application loads them into its own process space, so you take a performance hit there.
4. The Windows API has 95% of what you would need the C runtime to do. This isn't like Linux, where, you would die without libc trying to make heads or tales of syscalls and what not. On Windows, I struggle to think of a CRT call that could not be done nearly as simply as in SDK directly. For files there's CreateFile, WriteFile, etc. All of the basic string functions exist within the SDK, and the stuff to display formatted strings in the SDK is better than what the CRT gives you anyway. It's a bit more involved, but, there's articles out there on how to not have a CRT at all. In fact, applications that use the ATL and WTL frameworks even support not having the CRT code, just so you can write really, really tiny applications and gasp, COM components.
This is my sig.
You are 100% correct. The "problem" with those guys is that they did not even understand that they have to redistribute CRT DLL with their binaries even before the update. They got lucky there because on most systems, it is already there (I believe Vista has it out of the box, and probably some MS software will install it on XP - maybe even IE7/8?), so they got away with not distributing it. Now the update brought in a newer version of runtime, which of course the clients don't have, and they suddenly realize that they didn't distribute their dependencies properly. What does "DLL Hell" or side by side assemblies even have to do with it?
And, if they find it so hard to comprehend the idea that they have to give users the DLLs they link against, they could always just compile CRT statically and be done with it.
Most coders just write against API and should not care about binary compatibility.
A well-designed stable API should also ensure binary compatibility. That's almost a given with C APIs, fairly trivial to get with Java or .NET, and needs special attention but definitely possible with C++.
I really hate this /lib stuff. I remember the first time I make a C binary executable with GCC. It worked find on my Linux box, so it must work fine on any other Linux box I thought. Wrong! Turned out I needed to apt-get a whole bunch of libraries...
Seriously, all you are saying is that you didn't understand that your compiler was linking to a bunch of libraries, some of which were distributed with the OS and others were your responsibility to distribute when you created the application's setup/install package.
i-name =twylite [http://public.xdi.org/=twylite], see idcommons.net
"I was really pissed when I discovered that Microsoft had discontinued all versions of Visual Studio Express under the most recent one (2008, I believe?). I had to go and get a copy of VSE2005 off of bittorent since you could no longer download it from the Microsoft web site."
Then you got pissed and used BitTorrent for absolutely no reason whatsoever, because Microsoft are touting Visual Studio Express more than ever nowadays, it's become a core product for them.
http://www.microsoft.com/express/
What gave you the impression they'd discontinued them? Even on the standard Visual Studio pages links to express are and always have been clearly visible.
"It works fine for me" said the MS developer.
I put it down the the decline of Microsoft, I've been working as a MS dev for the past 15+ years, and since Bill left (a coincidence, I feel) the company has started a steady decline - wasting their money on frippery, attempting to get a new growth market, screwing with established systems in place of selling new stuff, and generally trying desperately to get your money off you. At least in the past, they were also focussed on making good technical stuff too.
Hands up anyone who knows what an "activation context" is! If you don't you have no idea what WinSxS does, how it does it or how to diagnose it when it goes wrong.
In my opinion, WinSxS is a good mechanism, or at least as good as Microsoft could have made it while working within the constraints of history. However, WinSxS cannot be used in the real world without properly understanding it, and achieving that understanding is very painful indeed. The MSDN documentation is piecemeal, appears incomplete and inaccurate in a few places and lacks a proper overview. I think the only reason I properly twigged what activation contexts are about is that I had recently written a mechanism that operated on similar principles (a thread-local stack of context-related information).
I wrote a Wiki page at work describing what (I think) WinSxS's motivation is, how it works and some of the problems it suffers from. I'd like to put it somewhere on the public internet - any suggestions? It should ideally be somewhere wiki-like where people can correct its inevitable inaccuracies without me having to maintain it, but I'm not sure it's appropriate for wikipedia.
"The Milliard Gargantubrain? A mere abacus - mention it not."
For those of you who do not know, the parent poster is talking about these topics:
A) A programming language called Brainfuck.
B) Homophobia.
C) How long the parent has known about Brainfuck.
It seems clear to me that there is a language called Brainfuck that everyone needs to be made aware of.
"His name was James Damore."
That's not a Visual Studio C++ issue, it's the way Windows memory management works. No matter what IDE/compiler/CRT you use, memory allocated by one dll cannot be (reliably) freed by another. It has to be freed by the same dll that allocated it. I'm not 100% sure, but I think you might also run into the same issue if you unload the dll and reload it before freeing the memory.
You could distribute source on Windows too.
Indeed. A stanard Windows DLL is not quite the same thing as an assembly, and as far as i know only assemblies have ever been "side by side." If you're doing plain old C++ on Windows, sxs doesn't enter into it, because side by side is a feature of the .net runtime.
Sorry, but you're wrong here. Microsoft is using the term "assembly" to refer to both managed and native DLLs since XP was released (which is before the first version of .NET was even out). Specifically, when you write a manifest file for your binary - which is something that first appeared in XP - you use the <assembly> element as root.
Also, SxS is quite specifically designed to work with native assemblies (for managed, GAC takes care of it).
Here is the reference:
Side-by-side (SxS) assemblies allow applications to specify which version of a system DLL or classic COM component to use, such as MDAC, MFS, MSVCRT, or MSXML.
Of course this all still has very little relevance to TFA, as they'd have troubles either way, SxS or not. The only difference is that with SxS they get a clear error report - "This program requires DLL version X.Y.Z" - while without it, they'd just get random crashes (or worse yet, silent data corruption) because of broken ABI between two versions of the binary.
If you use GlobalAlloc() to allocate the memory, then GlobalFree() always frees it. (I'm quoting from my nightmares here.)
The problem happens in VC++. The new operator eventually calls malloc() which eventually calls GlobalAlloc(), through chains of function calls that are fairly non-obvious, unless you read the disassembly or the source. GlobalAlloc() is a based Windows function, so every DLL links to the same system DLLs. The new and malloc calls are in the Microsoft Visual C++ libraries. Those libraries are loaded on a per DLL/EXE basis. As such, different VC++ DLLs can link to different VC++ run-time libraries, containing identical (or nearly identical) new and malloc functions but with different data areas.
Additionally, malloc() is optimized so it doesn't always call GlobalAlloc() whenever new memory is required. malloc() has it's own list of memory allocations, and that is where the problem is. A malloc() from one DLL with it's own data memory area knows nothing about another DLL's data memory area. As such, the free() call can't possibly succeed when the data was allocated in a different DLL.
Unfortunately, the torture doesn't end there. There are only two ways around the problem. Firstly, you can never pass memory allocations across DLL boundaries. Unfortunately, for some applications this doesn't work, for example COM and ActiveX controls. Alternatively, you can create a new type of memory handler to handle inter-DLL memory allocations. Microsoft created the IMalloc API for this reason. However, it is impossible to make the IMalloc API work across all possible failure modes. Also, IMalloc is not used by default for either new, delete, malloc() or free(). As such, the IMalloc API does not completely solve the inter-DLL issues, and introduces new problems of its own.
The IMalloc API is at the heart of COM, which is also at the heart of C#. Normally, C# might be a good language for soft real-time, long life systems. However, if any bug exists in any control using the IMalloc API, then all of the CLR can become unstable. As such, C# is the home of my biggest programming disaster ever. A program that is less reliable and runs thousands of times slower than the equivalent in C. In C/C++, some freedom exists to properly handle memory allocations, and data types are checked at compile time. In COM, it is almost impossible to understand all of the complexities of all of the memory allocations and data type conversions. As such, it is both easy to make mistakes with COM, and very difficult to work around them.
ActiveX/COM/DLLs are the root source of many serious security and reliability issues inside Windows. Historically, reliability and security issues were at least traceable to an executable. Now, all bets are off. ActiveX is present in Windows Explorer, Office and Internet Explorer, making it very difficult to effectively lock down the system. As such, system requirements for "a solid application" on "Microsoft Windows" represent an oxymoron. The result of these contradictory requirements is the application separation. Big and small applications use web servers running embedded Operating Systems or Linux (printers, Google, Bing), and display the results on a web browser on Windows.
In short, this bug is not a side effect of the Windows Memory Allocation API: GlobalAlloc() and GlobalFree(). It is a side-effect of DLLs under Microsoft Windows, and importantly the C Run-Time Library DLL implementation. As a result of the attempted workarounds, it has probably had as big of an effect on Windows as the old Intel 8088 segmented memory architecture.