Showing posts with label Developer Studio. Show all posts
Showing posts with label Developer Studio. Show all posts

Friday, July 19, 2013

unexpected precompiled header, simply rerunning the compiler might fix this problem

This post is about Microsoft's answer to the IT Crowd and their "did you try turning it off and on" running gag.

For years, we (at work) have been plagued with this particular error that seemed to happen spontaneously, hang around for a while then disappear, and today (with the help of Google) I've been able to track down an actual answer.

Microsoft explains the embarrassing truth here.

In a nutshell, precompiled headers are implemented cheaply as a straight memory dump complete with physical memory addresses.  When the compiler subsequently tries to read them back, ASLR has potentially scrambled it's little brain.

There are lots of fixes mentioned around the net, of varying levels of quality and security.  Microsoft has a hotfix but it only solves the problem for Visual Studio installs - we build using the Platform SDK.

For me, the sanest approach was:
  • download and install EMET from here
  • use EMET to disable "MandatoryASLR" and "BottomUpASLR" on the C compiler (cl.exe)
This leaves you with ASLR enabled for everything but the C compiler which doesn't cope.

Note, this has no impact on the output of the compiler - your programs will still be ASLR-enabled or not, depending on what switches you pass on the command line.  All we are doing here is fixing the actual compiler itself...



I hoped I'd never have to revisit this post, but today I had to. Looks like EMET can cause quite a bit of damage when you run it.

I tried using EMET 5.2 and it did resolve my problems with the C compiler.  As collateral damage, however, it took out Microsoft Office, AutoCAD 2011-2016, and even Internet Explorer.  Every one of them reported a vanilla error message "Attempt to access invalid address".

This looked to me to be related to either Data Execution Protection or perhaps to ASLR.  However, even though I completely disabled both of those features (through EMET), it didnt' help.  I've restarted so many times today you would not believe it.  Uninstalling EMET changed nothing.  I sat and manually uninstalled every Windows Update that had been applied in the last 48 hours and still no joy.

Eventually this post on the Microsoft Forums pointed me at an obscure registry entry and lo, it fixed the problem.  It would appear that EMET automatically puts in registry entries when it is installed, and does not remove them when it is uninstalled (no surprise there).

So, the fix was to go to

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options

and locate the application I was trying to use.  I removed the troublesome keys and voila, my apps work again.  (Actually, for many, I just removed the value for MitigationOptions which was 0x0000100)

Note: this is not something that you should attempt lightly.  No warranty implied or assumed.



Take Three.

It looks like the damage that EMET does is like herpes.  Every time I update Microsoft Office (ie, apply office updates), I need to go back in and patch up the registry settings again.  No idea why.  This must be that "my PC is so broken it needs to be reformatted and start again" that everyone talked about in the 80s.

Saturday, November 27, 2010

Why are my zeroes behaving like ones?

Guess the output of this program:

C:\>type x.c
#include <stdio.h>
#define ZERO 0
#define P(x) printf("x=%d",x)
main()
{
  P(ZERO);
}

C:\>.\x.exe
x=1

Duh, what?

Ok, I cheated, I didn't show you the stupid compiler option I managed to pass through the use of a slightly buggy makefile.


C:\>cl /D0 x.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

x.c
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.

/out:x.exe
x.obj

For those who don't memorise command-lines, that /D0 essentially is instructing the compiler to "define a value for the symbol 0" and the default value for definitions is "1".

Yes, the Microsoft VC90 compiler actually allows you to redefine the value of INTEGER tokens in your source code. Same thing happens at VC100.

C:\>cl /D0 x.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

x.c
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.

/out:x.exe
x.obj

C:\>.\x.exe
x=1

It could be argued that it only shows up if you have one preprocessor macro using the value of another preprocessor macro, and you have to use an unlikely command-line option, so its not that tragic. But seriously guys, Apple catches you doing that sort of stupid thing at command-line parsing time...

jeff$ cc -D0 x.c
<command-line>: error: macro names must be identifiers

... and those of that that grew up with ANSI-C use macros like this all the time.

#define NAME(l) l[0]
#define ADDR(l) l[1]
#define TYPE(l) l[2]

Having those 0, 1 and 2 become subject to the whim of the command-line is unthinkable.

This all came about because of a Python-generated command line. I thought I was creating

CL /DOPTION0 x.c

but a bug meant I created this instead:

CL /DO /DP /DT /DI /DO /DN /D0 x.c

So I'm a lot more careful now.

Someone did point out to me that "All computer programs are just 0s and 1s. Looks like this one was just 1s".

Computer geek humor.

Tuesday, March 31, 2009

".PDB files cannot be linked due to incompatible versions"

The message ".PDB files cannot be linked due to incompatible versions" can be displayed during builds, even if the .PDB file has just been created by the current compilation (ie, its just not possible that it was built by a different version of the compiler)

The problem is that the
mspdbsrv.exe process (which Microsoft uses to create PDB files) does not always terminate after linking.  If you have a mixed environment where you compile and link some modules with VC7.0 and then some with VC8.0, sometimes the 8.0 mspdbsrv.exe process hangs around and interferes with subsequent 7.0 compiles.

Solution: use the Task Manager to terminate it.