Static MFC code bloat problem from VC2010 is now in VC2008 SP1+security fix

EDIT – June 18th, 2011 – the below blog entry is out of date – click here for up to date information.

Thanks to Owen Wengerd from Outside the Box for letting me know about this one – it’s a big regression. Turns out the the code bloat release size problem introduced in VC2010 with MFC statically linked applications is now a problem in VC2008 SP1, thanks to the new security updates of April 12th.

Problem:

It all started with MS11-025. This security update caused a multitude of problems with MFC, some of which are mentioned in previous posts. This particular one is specific to VC2008 SP1, it appears after installing KB2465361 and then rebuilding your existing statically linked MFC application(s).

What happened is that themehelper.cpp now uses the function AfxLoadSystemLibraryUsingFullPath which resides in the afxglobals.cpp file (as an inline function, no less!). As we know from previous experience in VC2010, if your app has to pull in afxglobals.obj for any reason, a cascade effect occurs and approximately 1.2 megs are added to your release EXE size. For example, using the Appwizard to generate a simple MDI app with a classic menu and toolbar, and no visual styles, and building a release is 553KB before the security update, and 1763KB after the security update.

Solution:

Luckily there’s a quick solution. Owen suggested one solution which was similar to my previous blog entry about reducing static size in VC2010, which is to copy and edit the afxglobals.cpp file. But it’s actually easier than that. When I originally wrote this blog entry, I made this suggestion: we’ll include themehelper.cpp in our stdafx.cpp file without copying it, just including it directly, and use some preprocessor magic to make it use our own local version of the AfxLoadSystemLibraryUsingFullPath function instead of the one in afxglobals.cpp. But Owen realized that all you really need is your own local copy of the AfxLoadSystemLibraryUsingFullPath function somewhere in your app, and even better, there won’t be any duplicate symbol errors! So the full solution is:

1) open up your stdafx.cpp from your project
2) paste the following code after the #include "stdafx.h"


// this is our own local copy of the AfxLoadSystemLibraryUsingFullPath function
HMODULE AfxLoadSystemLibraryUsingFullPath(const WCHAR *pszLibrary)
{
	WCHAR wszLoadPath[MAX_PATH+1];
	if (::GetSystemDirectoryW(wszLoadPath, _countof(wszLoadPath)) == 0)
	{
		return NULL;
	}

	if (wszLoadPath[wcslen(wszLoadPath)-1] != L'\\')
	{
		if (wcscat_s(wszLoadPath, _countof(wszLoadPath), L"\\") != 0)
		{
			return NULL;
		}
	}

	if (wcscat_s(wszLoadPath, _countof(wszLoadPath), pszLibrary) != 0)
	{
		return NULL;
	}

	return(::AfxCtxLoadLibraryW(wszLoadPath));
}

3) Rebuild your app, and voila, it’s all better now.

About tedwvc
On this blog you'll find some tips and tricks for dealing with Visual C++ issues.

16 Responses to Static MFC code bloat problem from VC2010 is now in VC2008 SP1+security fix

  1. Pingback: The MFC Balloon « Outside The Box

  2. Owen Wengerd says:

    Thanks Ted for your excellent work! FWIW, I was able to simply define a custom AfxLoadSystemLibraryUsingFullPath (i.e. no need for any renaming acrobatics and including themehelper.cpp). This resulted in a file 100k slimmer than even the afxglobals solution. That’s like having my cake and eating it too!

    • tedwvc says:

      Hi Owen, you’re right, thanks! I had assumed I’d get a duplicate symbol without trying. Definitely will revise my blog entry with your suggestion.

  3. DemonKPZ says:

    I tried doing so but got the “duplicate symbol” error.

    Error 1 error LNK2005: “struct HINSTANCE__ * __cdecl AfxLoadSystemLibraryUsingFullPath(wchar_t const *)” (?AfxLoadSystemLibraryUsingFullPath@@YAPAUHINSTANCE__@@PB_W@Z) already defined in stdafx.obj
    Error 2 error LNK1169: one or more multiply defined symbols found

    • tedwvc says:

      I’m going to guess that this is because of compiler settings that don’t closely match the compiler settings of what MFC static libs were built with. Can you try creating a new project with the AppWizard (e.g. dialog based app) and see what happens. Then closely look at each page of the C/C++ compiler settings and see which ones are different from your project. You may have to create another CPP file (instead of including in your stdafx.cpp) and make sure that file has the same settings as what is used in MFC default generated appwizard project.

    • Ståle L. Hansen says:

      Are you really compiling with VS2008?

      I got this error when I tried the fix with VS2010, but it is only for VS2008.

  4. Ståle L. Hansen says:

    Are you really compiling with VS2008?

    I got this error when I tried the fix with VS2010, but it is only for VS2008.

  5. sean says:

    ugghh – latest update (~June 15, 2010) conflicts with this…

    • sean says:

      Looks like the latest update fixes the problems introduced in the previous update and the workaround is simply not needed anymore.

Leave a reply to Ståle L. Hansen Cancel reply