Visual C++ Precompiled Header Errors on Windows 7

Visual C++ Precompiled Header Errors on Windows 7

Rate This
  • Comments 24

Several customers have encountered the following error while using the Visual C++ compiler on Windows 7:

 

fatal error C1859: 'stdafx.pch' unexpected precompiled header error, simply rerunning the compiler might fix this problem

 

This error manifests under the following conditions:

·         The Visual C++ compiler is invoked on Windows 7.

·         Precompiled header (PCH) files are enabled.

·         /analyze is enabled (this is not a necessary condition, but it increases the probability of encountering this behavior).

 

Despite the error message’s suggestion, “simply rerunning the compiler” probably won’t help the situation. Indeed, the underlying cause of this error is far from “simple” as it stems from an interaction between our venerable precompiled header architecture and the new security enhancements in Windows 7.

 

Visual C++ Precompiled Headers and ASLR

Precompiled header files store the “state” of a compilation up to a certain point, and that state information can be reused in subsequent compiler invocations to significantly increase build throughput. For the past 15 years, our compiler has persisted precompiled headers to disk and reloaded them directly into virtual memory with 99.999% reliability and considerable performance gains. The tradeoff, however, was a degree of fragility in our architecture.

 

Since the PCH file itself contains internal pointers, it must be loaded at the exact same address in virtual memory where it was created. The pointers will be inaccurate if the PCH is loaded at a different address in subsequent compilations. To complicate matters, the PCH also contains polymorphic objects, and each polymorphic object contains its own virtual function table pointer (VFTP).  These VFTPs point to virtual function tables stored in modules. Therefore, if a polymorphic object in the PCH depends on a virtual function table in a particular module, that module must be loaded at the exact same virtual address as when the PCH was created.  If the module is loaded at a different address in subsequent compilations, the VFTP’s in the PCH will be inaccurate.

 

That’s a long-winded way of saying “both the PCH file and the modules it depends upon must not move between compilations!” The Visual C++ compiler will verify that both of these conditions are met before building, otherwise it will fail immediately with the above error. The latter condition bit us on Windows 7, which introduced more aggressive algorithms for Address Space Layout Randomization (ASLR). ASLR mitigates certain malware exploits by randomly relocating modules within a process. To circumvent ASLR randomization in Vista, the compiler modules were previously built with /dynamicbase:no back in Visual Studio 2008. This was insufficient in Win7 as randomization became more aggressive.

 

Our first attempt to fix the problem involved setting the preferred base address of each compiler module to a location that we considered “safe” (i.e. would decrease the odds of modules colliding sufficiently). Unfortunately, cascading rebases continuously thwarted our efforts as one module would move into the preferred address space of another, and the domino effect would continue until a module that the PCH used was rebased. Failures like this were difficult to diagnose and often involved subtle factors, such as process creation order (i.e. devenv.exe loads a module that cl.exe uses, etc) and the Native DLL Loader.  We were essentially locked in a losing battle with the Butterfly effect.

 

Our Solution

The majority of alternative solutions required either a substantial amount of work or an unacceptable performance hit. We finally decided to implement our own dispatch mechanism within the PCH data structures that eliminated the virtual function tables altogether. By “devirtualizing” the PCH data structures, we successfully eliminated the second criterion: compiler modules can now move about the process without breaking the precompiled header file.

 

This fix will be available in the final release of Visual Studio 2010, and a hotfix for Visual Studio 2008 will be released shortly. If you are encountering this problem in the interim, please try the following workarounds:

·         Disable /analyze (if enabled).

·         Invoke a clean build.

·         Reboot your machine.

·         Disable PCH files.

 

Thanks,

Mark Roberts

Visual C++ Compiler Team

 

**UPDATE**

The public patch for Visual Studio 2008 SP1 has been released. You may download it here.

 

  • Does the compiler write version and OS checking information into the PCH file as well? My experience has been that the VS2005 SP1 compiler crashes if you switch OSes in a dual-boot configuration on the same project, and I have to manually clean the PCH to fix it. I do this when I need to develop and test on multiple OSes. Unfortunately, I don't have VS2010 in a dual-boot configuration to test.

  • Does this affect the VS2005 compiler as well?

  • > To circumvent ASLR randomization in Vista, the compiler modules were previously built with /dynamicbase:no back in Visual Studio 2008. This was insufficient in Win7 as randomization became more aggressive.

    Is there no way to disable ASLR for a module other than /FIXED:NO now then?

    Are there more details about the changes in ASLR behaviour on Win7 anywhere?

  • When will something like position independent code support be added to the PE format?

  • Position independent code is not really supported by PE, what we have instead is rebasing. When a DLL (yes, only dll since exe files are not movable) is loaded in, all the offsets are set to their linked addresses but the dll is movable in memory because it also stores a list of memory addresses that would need to be changed.

    This is supported in the operating system by the executable loader. It loads in the dll, checks whether it can be loaded into the desired address, if not it will load it in somewhere else with enough free space and it rebases all of the offsets.

    In the end PIC and rebasing are to methods to achieve the same goal and they both have different benefits and drawbacks. Since rebasing is supported there is little need to support PIC.

  • I wan to clear up a comment from my previous post. It isn't that exe files are not movable, it is more like they are not movable by default. Because of this rebasing the executable isn't needed since it is always the first thing to be loaded into a processes memory space so collisions cannot occur.

    With ASLR being introduced into Vista, this has caused the creation of rebasable executable files.

  • Hello,

    RE: VS 2005

    We have not received a single bug report for this issue on Visual Studio 2005, but it is conceivable that this problem could exist in that release. If someone does encounter this behavior on VS 2005, please email me directly at Mark.B.Roberts _at_ microsoft.com.

    Phaeron, which OS versions are you switching between?

    To James:

    Microsoft has not published any of the Win7 changes to the ASLR implementation, but technically, /FIXED has always been the only guarantee that ASLR would be "disabled" for a given module. Of course, that switch will also prevent the module from being loaded AT ALL if it cannot acquire it's preferred base.

    To Ben and Crescens2k:

    I can't comment on whether position independent code will be included in the PE format anytime soon; however, it should be noted that such a feature would not have enabled a fix for this bug. Crescens2k, exe files CAN be rebased just like dll files. They both have preferred base addresses and can be fixed up by the loader. You can also invoke LoadLibrary on an exe file so it is loaded at point after process creation (whereby it could collide with another module).

    Thanks,

    Mark Roberts

    Visual C++ Compiler Team

  • I'm seeing the same error on Win 2008.  A rebuild doesn't fix the problem for me.

  • Hi mrk,

    A rebuild may not always work. Your best bet is to restart the machine assuming you are encountering the error due to ASLR.

    Theoretically, this error could occur on any operating system, but on Windows 7, it started to occur frequently enough to seriously disrupt builds. Regardless of the OS, our new fix should eliminate this issue if ASLR is the cause.

    Thanks,

    Mark Roberts

    Visual C++ Compiler Team

  • Yeah I'm going to try the reboot too.

    It's strange, I just started seeing the problem a day or two ago.  So I've been doing some searching about this error (didn't find much though) ... I did read said that you can start to see the problem after a reboot, or go away after a reboot ... Which doesn't totally match up with my experience (this computer has been up for 97 days right now), and has compiled the same project without the C1859 error.  The only update applied since last successful compile was a (mandatory) Live Messenger update.

    .. off to save a few things and try a reboot

  • ... not seeing the C1859 anymore after reboot; thanks Mark.

  • I blame tiredness -_-;

    Reread what I posted this morning and I was thinking why did I write that.

    For me, I've never seen the need to make an executable rebasable. If there is any chance that code would need to be executed by another executable file then I will always put it into a library.

  • When I tried to compile and execute first MFC sample in vs2010 beta2 on WinXp-sp3 while I haden't add

    any thing to wizard generated code; I encountered this compiler error:

    ...C1903: unable to recover from previous error(s); stopping compilation  ...\windows\v7.0a\include\objidl.h 11281

    ...C2059: syntax error : ')' ...\windows\v7.0a\include\objidl.h 11281

    ...C2061: syntax error : identifier '__RPC__out_xcount_part' ...\windows\v7.0a\include\objidl.h 11280

  • VS2010 is shaping up to be a great product.  I have been using the new C++0x lambda functionality and find that they go hand-in-hand with the templates in the algorithm header.  The new random number facilities are fabulous -- the C++0x people did a great job of designing this and you guys did a great job of implementing it.

    If time were not a constraint it would have been nice to see variadic templates, but I suppose it is better to wait than to have a rushed feature.

  • I have a Visual C++ Runtime error on my Windows 7 x64 while running some programs. for example - adobe audition. I tried to fix this error by registry cleaners and other cleaning tools, but it did not work :( please tell me how to fix this problem

Page 1 of 2 (24 items) 12