Notes for C++ Development on Windows
I’ve been writing a lot of C++ code at ArangoDB lately. Most people want their databases to run on top of some Linux distro, which makes perfect sense, but ArangoDB supports Windows as well (at least they did, until version 3.12). Even though that comes with extra maintenance costs, I think it’s a good idea. By building your project with different compilers, you’re making sure the code stays portable and uses only standard features. Clearly, multiple compilers can point out more potential issues together. By testing our project on different operating systems, we see how it behaves under various circumstances, thus making sure it doesn’t rely on platform specific behavior. I once stumbled across a stack overflow that was mostly reproduced when running the tests on Windows, because the stack size is by default smaller (1MB compared to 10MB on Linux). Even concurrency issues are often uncovered this way, because different operating systems use different schedulers.
Compilers
The staple compiler on Windows is MSVC. A good alternative is
clang. If you care about MSVC compatibility, check out
clang-cl, a driver program for clang that attempts to be compatible
with MSVC’s cl.exe.
There’s also a way to get GCC on Windows, but I never tried it, one can check out MinGW if
he’s so inclined.
I find compiling on Windows slower compared to Linux, probably due to NTFS
and ext4 differences. More so, I sometimes experienced lag when using the computer during
longer builds, so I decreased the CPU and IO priority of the compiler and linker processes.
1 | Windows Registry Editor Version 5.00 |
In the example above, I am setting the priority to below normal, which works great for me. Here’s a list of hex values, so you can customize it:
- Low: 00000001
- Below Normal: 00000005
- Normal: 00000002
- Above Normal: 00000006
- High: 00000003
In case that’s not enough, you could limit the number of cl.exe
processes (to 8, for example) by passing the /p:CL_MPCount=8
argument to MSBuild.
If you’re using an IDE, most probably there’s a setting for that.
Debuggers
On Windows, I usually go for lldb. You need LLVM for Windows, which is
available on their GitHub releases page. You can also get
GDB, but it has the disadvantage of not being able to load Windows crash dumps.
Sometimes, during debugging, I have to observe the assembly instructions. In case of x86-64 programs,
I prefer the Intel syntax, which can be configured from the .lldbinit
file, placed in the user directory:
1 | settings set target.x86-disassembly-flavor intel |
These two debuggers are great for most use cases, but for debugging Windows drivers I had to use WinDbg. Although WinDbg can be used to debug any program, not just drivers, I used it solely for that.
Crash Dumps
Crash Dumps are the Windows counterpart of Linux Core Dumps. When a program crashes, a dump file (.dmp) is written
to disk. This can be later used to debug and analyze the program (memory content, registers), at the moment of the crash.
By default, crash dump generation is disabled, but it can be enabled through the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps
registry key.
1 | Windows Registry Editor Version 5.00 |
How to configure it:
- DumpFolder - where the dump files are to be stored (
%LOCALAPPDATA%\Temp
) - DumpCount - maximum number of dump files in the folder (64)
- DumpType - Custom/Mini/Full (Full)
- CustomDumpFlags - only used when DumpType is set to 0
Here’s a Python one-liner to generate a DumpFolder REG_EXPAND_SZ from a custom string:
1 | ',00,'.join([hex(ord(c))[2:] for c in '%LOCALAPPDATA%\Temp']) + ',00' |
To test the settings, compile and run any broken C++ program.
1 | int main(void) { |
Running this program will generate a crash dump in the folder pointed by DumpFolder. The dump will be named executable.pid.dmp.
In my case, that was broken.exe.2940.dmp, because I called the executable broken.exe
and the process ID was 2940
.
Load the executable alongside its core in lldb:
1 | lldb broken.exe -c broken.exe.2940.dmp |
If you’re used to GDB, but are new to lldb, check out this nice command map.