Mixing C runtime library versions

When compiling code with Microsoft's Visual C/C++ compiler, a dependency on Microsoft's C runtime library (CRT) is introduced. The CRT can be linked either statically or dynamically, and comes in several versions (different version numbers as well as in debug and release variants).

Complications arise when libraries linked into the same program use different CRTs. This happens if they were compiled with different compiler versions, or with different compiler flags (static/dynamic CRT linkage or release/debug switches). In theory, this could be made to work, but in practice it is asking for trouble:

  • If the CRT versions differ (either version number or debug/release flag), you can't reliably share objects generated by CRT A with any code that uses CRT B. The reason is that the two CRTs may have a different memory layout (structure layout) for the that object. The memory location that CRT A wrote the object size to might be interpreted by CRT B as a pointer, leading to a crash when CRT B tries to access that memory.
  • Even if the same CRT version is included twice (once statically, once dynamically linked), they won't share a heap. Both CRTs track the memory they allocate individually, but they don't know anything about objects allocated by the other CRT. If CRT A tries to free memory allocated by CRT B, that causes heap corruption as the two CRTs trample on each others feet. While you can freely share objects between CRTs, you have to be careful whenever memory is allocated or freed. This can sometimes be managed when writing C code, but is very hard to do correctly in C++ (where e.g. pushing to a vector can cause a reallocation of its internal buffer).

Accordingly, having multiple CRTs in the same process is fragile at best. When mixing CRTs, there are no tools to check whether objects are shared in a way that's problematic, and manual tracking is subtle, easy to get wrong, and unreliable. Mistakes will lead to difficult-to-diagnose bugs and intermittent crashes, generally at the most inconvenient times.

To keep your sanity, ensure that all code going into your program uses the same CRT.1 Consequently, all program code, as well as all libraries, need to be compiled from scratch using the same runtime library options (/MD or /MT). Pre-compiled libraries are a major headache, because they force the use of a specific compiler version to get matching CRT version requirements. If multiple pre-compiled libraries use different CRT versions, there may not be any viable solution at all.

This situation will improve with the runtime library refactoring in VS2015, which promises CRT compatibility to subsequent compiler versions. Thus, this inconvenience should mostly be solved in the future.


1 Dependency Walker can be used to list all dynamically linked CRT versions. I'm not sure whether that can be done for statically linked CRTs, I generally avoid those.


Installing Windows 95 inside QEMU on Linux

If you can just install Windows 95 inside QEMU and it magically works consider yourself lucky. I tried this and got an error message that I need to create a FAT partition first where the installer can place some files. That's where it all began.

Installing

  • Create the disk image. dd if=/dev/zero of=hda bs=$(( 1024*1024 )) seek=1000 count=0. That way you create a sparse 1GB file.
  • Get a FreeDOS Floppy and CD image and install FreeDOS inside QEMU, there you can partition your disk. qemu -hda hda -fda fd0 -cdrom cdrom-img -boot a.
  • Insert the windows CD, run qemu with -cdrom /dev/cdrom -boot c so you get to the FreeDOS prompt, then go to the cdrom drive and run setup. The setup should work then

Getting networking up inside Windows

  • You need the Realtek rtl8139 driver, other network cards won't work (ne2000 at least doesn't). So run qemu with -net user -net nic,model=rtl8139.
  • Windows 95 unfortunately doesn't have the driver for the rtl8139, so you need to get it onto the system. Download it from well, the Realtek driver download page. Unzip it, put it onto a floppy, create an image of that floppy and run qemu with -fda image.
  • Then setup the networking under windows, reboot and you should be able to access the internet.