Ch20: Freestanding

中文(简体)

Why This Chapter Is the Payoff

Every chapter so far assumed an operating system underneath you: a heap behind malloc, a console behind print, an unwinder, a loader, a C library. This chapter removes all of it and asks what is left. The answer is: everything this book taught you, minus the parts that were never anyone's idea of a good design.

The standard's own definition of the two kinds of implementation is short, and it is the reference for everything here: cppreference — freestanding. Read it once before continuing, because the rest of this chapter is about the gap between that page and what a compiler actually ships.

KindWhat it promisesWhere you meet it
Hosted __STDC_HOSTED__ is 1. A program has a main, may have several threads, and gets the whole standard library. Desktop, server, phone, a normal application build
Freestanding __STDC_HOSTED__ is 0. Whether a program has main at all is implementation-defined, threads are implementation-defined, and the standard library shrinks to a list of headers — a list that C++ left mostly empty for thirty years. Kernel, bootloader, firmware, an embedded board, a WebAssembly module

A freestanding implementation is not a smaller C++. It is C++ with the operating system taken away, and the interesting question is not "can the compiler still compile" — of course it can — but "which of the things you were taught to rely on were actually the operating system, and which were the language".

What This Chapter Reads, in Order

  1. 20.1 What Freestanding and Hosted Implementations Are — the standard's definition, __STDC_HOSTED__, and why -ffreestanding on your desktop is not a freestanding environment.
  2. 20.2 C Freestanding vs C++ Freestanding — C had a usable freestanding mode in 1989. C++ had a promise.
  3. 20.3 The C++03 Freestanding Lie — a freestanding mode that required exceptions, RTTI and new, and did not even have std::addressof.
  4. 20.4 Why Linus Torvalds Called It a "BLOODY STUPID IDEA" — the 2004 message, and which of its four claims hold.
  5. 20.5 What the Defense Never Does: Build a Cross Compiler — the argument always comes from someone with a hosted toolchain.
  6. 20.6 What Is Still Missing Today — the header list, the C++26 hole, and std::array.
  7. 20.7 Default Heap Storage: new and delete — one global heap that is not enough for a kernel, measured.
  8. 20.8 RTTI and dynamic_cast — the tables and the vtables you cannot link.
  9. 20.9 Legacy Exceptions Cannot Exist Here — the mechanism that needs an operating system.
  10. 20.10 Herbceptions: the Only Error Handling That Exists Here — the same mechanism, one linker symbol, and [domain](code).
  11. 20.11 Thread-Local Storage, Floating Point, and Startup — the three features nobody lists.
  12. 20.12 std::move, std::addressof, and the Utility Headers — the absence you cannot code around.
  13. 20.13 fast_io Is a Freestanding I/O Library — a program with zero undefined symbols.
  14. 20.14 Watch: Freestanding C++ — Past, Present, and Future — Ben Saks, CppCon 2019.

The One-Sentence Version

C++ was designed as a hosted language and spent thirty years insisting that freestanding was a corner case, while the code that runs on the most devices in the world — kernels, firmware, bootloaders, GPUs — could not use it without switching off the language's own features and half its library. That is the criticism Linus Torvalds made in 2004, it was correct, and this chapter is about what it takes to be on the right side of it today: no legacy exceptions, no RTTI, no hidden global heap, no hosted library — and an I/O library that does not assume any of them.