Current version

v1.10.4 (stable)

Navigation

Main page
Archived news
Downloads
Documentation
   Capture
   Compiling
   Processing
   Crashes
Features
Filters
Plugin SDK
Knowledge base
Donate
Contact info
Forum
 
Other projects
   Altirra

Search

Archives

01 Dec - 31 Dec 2013
01 Oct - 31 Oct 2013
01 Aug - 31 Aug 2013
01 May - 31 May 2013
01 Mar - 31 Mar 2013
01 Feb - 29 Feb 2013
01 Dec - 31 Dec 2012
01 Nov - 30 Nov 2012
01 Oct - 31 Oct 2012
01 Sep - 30 Sep 2012
01 Aug - 31 Aug 2012
01 June - 30 June 2012
01 May - 31 May 2012
01 Apr - 30 Apr 2012
01 Dec - 31 Dec 2011
01 Nov - 30 Nov 2011
01 Oct - 31 Oct 2011
01 Sep - 30 Sep 2011
01 Aug - 31 Aug 2011
01 Jul - 31 Jul 2011
01 June - 30 June 2011
01 May - 31 May 2011
01 Apr - 30 Apr 2011
01 Mar - 31 Mar 2011
01 Feb - 29 Feb 2011
01 Jan - 31 Jan 2011
01 Dec - 31 Dec 2010
01 Nov - 30 Nov 2010
01 Oct - 31 Oct 2010
01 Sep - 30 Sep 2010
01 Aug - 31 Aug 2010
01 Jul - 31 Jul 2010
01 June - 30 June 2010
01 May - 31 May 2010
01 Apr - 30 Apr 2010
01 Mar - 31 Mar 2010
01 Feb - 29 Feb 2010
01 Jan - 31 Jan 2010
01 Dec - 31 Dec 2009
01 Nov - 30 Nov 2009
01 Oct - 31 Oct 2009
01 Sep - 30 Sep 2009
01 Aug - 31 Aug 2009
01 Jul - 31 Jul 2009
01 June - 30 June 2009
01 May - 31 May 2009
01 Apr - 30 Apr 2009
01 Mar - 31 Mar 2009
01 Feb - 29 Feb 2009
01 Jan - 31 Jan 2009
01 Dec - 31 Dec 2008
01 Nov - 30 Nov 2008
01 Oct - 31 Oct 2008
01 Sep - 30 Sep 2008
01 Aug - 31 Aug 2008
01 Jul - 31 Jul 2008
01 June - 30 June 2008
01 May - 31 May 2008
01 Apr - 30 Apr 2008
01 Mar - 31 Mar 2008
01 Feb - 29 Feb 2008
01 Jan - 31 Jan 2008
01 Dec - 31 Dec 2007
01 Nov - 30 Nov 2007
01 Oct - 31 Oct 2007
01 Sep - 30 Sep 2007
01 Aug - 31 Aug 2007
01 Jul - 31 Jul 2007
01 June - 30 June 2007
01 May - 31 May 2007
01 Apr - 30 Apr 2007
01 Mar - 31 Mar 2007
01 Feb - 29 Feb 2007
01 Jan - 31 Jan 2007
01 Dec - 31 Dec 2006
01 Nov - 30 Nov 2006
01 Oct - 31 Oct 2006
01 Sep - 30 Sep 2006
01 Aug - 31 Aug 2006
01 Jul - 31 Jul 2006
01 June - 30 June 2006
01 May - 31 May 2006
01 Apr - 30 Apr 2006
01 Mar - 31 Mar 2006
01 Feb - 29 Feb 2006
01 Jan - 31 Jan 2006
01 Dec - 31 Dec 2005
01 Nov - 30 Nov 2005
01 Oct - 31 Oct 2005
01 Sep - 30 Sep 2005
01 Aug - 31 Aug 2005
01 Jul - 31 Jul 2005
01 June - 30 June 2005
01 May - 31 May 2005
01 Apr - 30 Apr 2005
01 Mar - 31 Mar 2005
01 Feb - 29 Feb 2005
01 Jan - 31 Jan 2005
01 Dec - 31 Dec 2004
01 Nov - 30 Nov 2004
01 Oct - 31 Oct 2004
01 Sep - 30 Sep 2004
01 Aug - 31 Aug 2004

Stuff

Powered by Pivot  
XML: RSS feed 
XML: Atom feed 

§ The dreaded "application configuration is incorrect" error

Periodically, I get asked the following question:

"When I build my program with Visual C++, it runs fine on my own machine, but whenever other people try running it they get an 'application configuration in incorrect' error. How do I fix this?"

...after which I groan and ask the person if they're doing anything else for the rest of the day, because this'll take a while to explain, and probably a lot longer to fix.

This error usually means that your program is set up to use the Visual C++ runtime library (CRT) in DLL mode, and the operating system can't find the versions that your program references. Should be simple -- find the right DLLs and include with the program? Well, no, it's a lot more complicated than that.

Where the CRT references come from

The reference to the C runtime library is added by the compiler, driven by the "Runtime Library" setting:

[Project Settings - Runtime Library]

There are four settings here, arising from two choices: whether you want to use the statically linked (.lib) or dynamically linked (.dll) version, and whether want debugging features enabled or not. If you're statically linking the CRT, then the CRT is being merged directly into your EXE or DLL -- congratulations, you're done! You can skip to the end, because you don't have to worry about anything I'm describing here. Therefore, you should ask whether you need the DLL version of the CRT at all. If you're making a small, self-contained executable that doesn't use managed code, doesn't need to exchange heap memory with other DLLs in the same process and is less than a megabyte, you should just statically link the CRT and be done with it. Otherwise, you've got to pay attention to the CRT DLL that you're using.

What happens at compile time is that the compiler embeds a reference in the .OBJ file that tells the linker to include the library file CRT that you've selected. This can be msvcrt.lib or msvcrtd.lib for the DLL version, and libcmt.lib or libcmtd.lib for the statically linked version. The linker pulls the required lib from the standard LIB path and automatically links your executable with the CRT. This is why you can simply use "cl hello.cpp" or "cl /MT hello.cpp" on the command line, and everything will be automatically set up for you.

Which DLL do I need?

That raises the question of which DLL you actually need. Well, it could be one of several:

There are additional DLLs associated with some C++ library and mixed mode features that you may need, denoted by 'm' and 'p' suffixes.

In current versions of Visual Studio, these DLLs are meant to be installed into the system and are installed via a program called vcredist_x86.exe or vcredict_x64.exe. You might be able to get away with not redistributing the DLL, especially since the VS2005 and VS2008 DLLs are typically installed by .NET, but you're taking a big risk by doing this and you really shouldn't rely on it. Microsoft's advice has always been that you need to redistribute the DLL yourself if you are using it, and this is good advice, because you're rolling the dice on the user's machine if you aren't. You don't want to spend time fielding reports like "your popup tool stops working when I uninstall Photoshop."

Microsoft's CRT installation advice, by the way, is in an article on MSDN called "Redistributing Visual C++ Files":
http://msdn.microsoft.com/en-us/library/ms235299.aspx?ppud=4

Avoiding installation

There are times that you want to avoid any installation on the target system, such as when you're pushing out daily builds to people on a team or on an automated test farm. In this case, you can copy the runtime DLLs onto the target system so that they're only used by a specific executable. In older versions of Visual C++, you could just copy the CRT DLLs next to the EXE. This no longer works starting with VS2005, where you'll get an error message about the DLL being incorrectly installed. This happens because starting with VS2005 the CRT relies on the manifest system to select and bind the CRT version. The short answer is that you need to copy the appropriate directories from the VC\redist\x86 or VC\redist\amd64 directory instead. In other words, for a VS2005-built application, you should have a directory called Microsoft.VC80.CRT next to the EXE, with DLLs and a .manifest file inside.

For people using VS2008, there is a nice gotcha involved. In my experience, due to the way CRT manifest binding works in that version, you must use the RTM version of the CRT DLLs for private deployment even if the application was built with VS2008 Service Pack 1. The reason appears to be that by default the built EXE or DLL references the RTM version and redirection is used to bind to the latest version, but this mechanism doesn't work when the CRTs are deployed as private assemblies.

Another gotcha you need to watch out for is that the debug CRT is not a redistributable component, so make sure you're not shipping modules that require it.

If after doing all of this you are still getting misconfigured application errors on launching your program, then you've got a bigger problem.

What happens when you're not paying attention

What happens if you have inconsistent Runtime Library settings in modules in your program? Well, you get the dreaded but common LNK4098 warning:

LINK : warning LNK4098: defaultlib 'MSVCRTD' conflicts with use of other libs; use /NODEFAULTLIB:library

What this means is that the linker has detected that you have CRT conflicts and has picked one of them to resolve it. Some people just shrug off the warning since it's not an error, and that's a bad idea since you don't know which CRT version you're going to get. Others follow the linker's poor advice and add MSVCRTD to the "Ignore Specific Libraries" list. While this gets rid of the warning, it creates a far worse problem relating to the manifest that I described earlier. The manifest is an XML file that is either next to the .EXE (foo.exe.manifest) or merged into the EXE/DLL itself as a resource of type RT_MANIFEST, and looks like this:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.VC80.DebugCRT' version='8.0.50727.762'
          processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </dependency>
</assembly>

Prior to the manifest, DLLs were bound solely by the import list in the EXE/DLL, which gives the name of a DLL and a list of entry points to import. Manifests additionally say which version of the DLL to use. That there are two separate mechanisms involved in the CRT DLL resolution process should send a chill up your spine. Either the import list or the manifest can cause your program to fail to load, and the problem is that most people are only familiar with how to debug the import list, which leaves them dumbfounded when it's actually the manifest that's the problem. Remember that LNK4098 example I showed earlier?  Well, after adding /NODEFAULTLIB:MSVCRTD, the executable's import list only shows MSVCRT.DLL, and all is good... except for the manifest:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.VC80.DebugCRT' version='8.0.50727.762'
        processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </dependency>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50727.762'
        processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </dependency>
</assembly>

Surprise! Our guinea pig executable now references both the debug and non-debug versions of the CRT and will fail to load if either is missing. I'll resist the urge to make an "XML makes it better" joke... oops, too late.

It can get much worse than this when you realize that not only can you have debug and non-debug versions of the CRT involved, but also versions from different service packs and even different versions of the compiler -- I've seen cases where people had a VC8 CRT and three versions of the VC9 CRT in the manifest. At that point you're fairly screwed from the deployment side and you need to fix the build itself. The right way to fix this is to hunt down every path that is bringing in the wrong version of the CRT and make sure that all of them are rebuilt with the same version of the compiler, at the same service pack level, and with the same Runtime Library setting.

The nightmare of tracking this down is when you have static libraries (.libs) checked in, either pre-built or from a vendor. This is when you discover that the prebuilt .lib doesn't rebuild properly from source anymore, or it wasn't ever upgraded and rebuilt in the last compiler upgrade, or you can't find the source, or it comes from a vendor and you have to negotiate with them to get an updated version. It's very important to make sure that everything required to rebuild your prebuilt libs is checked into source code control and that you track the upstream sources for all of your externally supplied libs, or you could get into a situation where you can't resolve a mixed CRT version situation properly. The other nightmarish part is actually finding the .libs that are causing the problem. If the problem is a debug/release conflict, you can link with /VERBOSE and check who is bringing in the debug CRT, but if it's a version conflict, this is the only good way I know of is by brute force scanning the libs:

for /r %x in (*.lib) do (@echo "%x" && strings -a "%x" | grep -r- "Microsoft.VC")

Track down and fix each offender one by one until there is only one CRT left in the manifest.

There is an alternative option, by the way, which is that you can force the manifest. The way the build process normally works is that LINK produces a .manifest file, and the manifest tool (mt.exe) is then called to merge that into the executable. You can disconnect this link and reconfigure the Manifest Tool step to reference a manifest of your choosing instead. I haven't explored this path, though, and it's risky since you're still combining components that were intended to be used with a different version of the CRT than it being loaded. It may be your only option if for some reason you can't fix and rebuild the offending modules.

When it turns ugly

One aspect where this can turn ugly is when you have external components supplied by a vendor. In that case, you may either have a .lib that you can't rebuild yourself or a .dll that has its own CRT version reference. In that case, you have to hope that everything references exactly the same version or that you can force them to do so by fudging the manifest. Static libraries are such a problem in this regard that some vendors have stopped distributing .libs entirely and only distribute code to licensees in either source code form or as a DLL. You may be in trouble if it turns out that all you have is a .lib built with Visual Studio 2005 and the company that gave it to you is now out of business. Source code form, of course, will give you the most control and allow all of these problems to be avoided, but may be expensive or infeasible.

The other ugly case has to do with an ATL security patch that went out several months ago. This patch can cause a CRT version mismatch problem in your build because it also updates the CRT and can change the version referenced by your build even if you aren't actually using ATL. I haven't seen this problem on my own computers but I have seen ugly cases where CRT load failures started happening in automated builds because the patch wasn't deployed consistently between developer machines and autobuild machines. This is how you get nasty situations where two people with apparently identical development configurations compile the same program and only one of the builds works in the field: only one of them has the ATL update installed. If you have version problems and see both the SP1 and the ATL update version of the CRT showing up in the manifest, you've been bitten by this problem and need to either force the CRT version or deploy the patch to all build and dev machines.

What this all comes down to is that you need to track all dependencies that are included in your program and test both the internally deployed and installed forms of your program on a clean, unpatched install of Windows to be sure that it'll work properly in the field.

The future

CRT deployment is apparently changing in Visual Studio 2010, as the CRT is back to using a plain, non-WinSxS DLL. I don't know how this will work out, but it's possible that much of what I've described above will no longer be a problem in VS2010. Until then, keep your hex editor or resource editor handy, and check the manifest every time your program fails to load on someone's machine.

Comments

Comments posted:


Wow, that's great news that VS2010 is going back to a sane situation again.

One of the reasons why I've just stuck with VS2003 is because of the total screw up in the CRT deployment that they added as an "improvement" for VS2005.

I think I first saw that this was all going to be monumentally hosed up from this post:
http://blogs.msdn.com/martynl/archive/20..

The tried and true way to avoid DLL hell issues is to make your deployment as self contained as possible and just simply have your dependent DLLs installed in the same folder as the executable.

I was really suprised at the massive screwed up direction that the VC libraries team took this into, it seemed just plain idiotic really. Probably they had some people theorizing about things who never had any actual deployment experience.

It was easy to see the train wreck coming from the first announcement of it.

Michael G - 21 03 10 - 15:03


Hugely interesting article, thank you very much for posting it!

Marcel - 21 03 10 - 22:23


DLL hell was bad, but SxS is much, much worse...

Maxii - 22 03 10 - 00:04


"DLL hell was bad, but SxS is much, much worse..."
Or to be more precise, SxS hell. SxS can be great, it is unfortunate that it is poorly documented, particularly in the early days. Someone should write a book about it, it would help a lot.

Yuhong Bao (link) - 23 03 10 - 04:24


BTW, MSXML tried SxS with the 4.0 release, but got rid of it with 6.0.

Yuhong Bao (link) - 23 03 10 - 04:41


SxS Hell is an extension of DLL hell.

Great article Avery, but how come you haven't touched OpenMP issues and static .vs. dynamic linking? :)

Igor Levicki (link) - 25 03 10 - 06:53


> Great article Avery, but how come you haven't touched OpenMP issues and static .vs. dynamic linking? :)

What, you wanted this post to be _longer_?? :)

Phaeron - 25 03 10 - 16:31

Comment form


Please keep comments on-topic for this entry. If you have unrelated comments about VirtualDub, the forum is a better place to post them.
Name:  
Remember personal info?

Email (Optional):
Your email address is only revealed to the blog owner and is not shown to the public.
URL (Optional):
Comment: /

An authentication dialog may appear when you click Post Comment. Simply type in "post" as the user and "now" as the password. I have had to do this to stop automated comment spam.



Small print: All html tags except <b> and <i> will be removed from your comment. You can make links by just typing the url or mail-address.