5.3.11 · D1Build Systems & Toolchain

Foundations — GCC - Clang flags — optimization (-O0 to -O3, -Os), warnings (-Wall, -Wextra), sanitizers

1,855 words8 min readBack to topic

Before you can read the parent note fluently, you need a small pile of words and pictures. This page builds each one from nothing, in the order that each depends on the last. If a term appeared on the parent page and you weren't 100% sure what it meant — it is defined here.


1. Source code, the compiler, and machine code

Look at the top row of the figure below: the same idea (s = a + b) exists as human text on the left and as CPU instructions on the right. The compiler is the arrow between them.

Figure — GCC - Clang flags — optimization (-O0 to -O3, -Os), warnings (-Wall, -Wextra), sanitizers

See the Compilation Pipeline (preprocess-compile-assemble-link) for the full journey; here we only need "text in, instructions out".


2. The - flag notation


3. Registers vs. memory — the picture behind "optimization"

To understand why -O0 is slow and -O2 is fast, you need one picture of where a number lives while the program runs.

The figure below draws the CPU with its few fast registers on the left and the big slow memory shelf on the right. An arrow crossing between them is a load (memory→register) or store (register→memory) — and every such crossing costs time.

Figure — GCC - Clang flags — optimization (-O0 to -O3, -Os), warnings (-Wall, -Wextra), sanitizers

The consequences of code size (from -O3) are about the CPU Caches and Instruction Cache; the "do 8 additions at once" trick is SIMD and Auto-Vectorization.


4. Compile time vs. run time — two different clocks

Warnings and sanitizers are wildly different tools, and the only thing that separates them is when they act.


5. Static vs. dynamic (the same idea, named)


6. Undefined Behaviour (UB) — the keystone

This is the single most important concept the parent page leans on, so it gets its own picture.

The figure below shows two roads from the same source. On the safe road (correct program) -O0 and -O2 reach the same destination. On the UB road, the two levels split apart — same source, different answers — which is exactly the parent's "crashes at -O2, works at -O0" mystery.

Figure — GCC - Clang flags — optimization (-O0 to -O3, -Os), warnings (-Wall, -Wextra), sanitizers

Go deeper on this in Undefined Behaviour in C/C++.


7. Shadow memory & redzone — how ASan sees

The parent's ASan explanation uses two words worth a picture.

Picture a valid array in green with red "do not enter" strips glued on both ends; the shadow table is a little ledger marking each region OK or POISON. A write into red is caught instantly.


8. Two tiny extras the parent assumes


How the foundations feed the topic

source code text

compiler translates

machine code

registers vs memory

optimization levels O0 to O3

compile time vs run time

warnings Wall Wextra

sanitizers fsanitize

undefined behaviour

shadow memory redzone

debug info g

5.3.11 GCC and Clang flags

Each foundation on the left is a word you now own; together they let you read every callout on the parent topic.


Equipment checklist

Cover the right side and test yourself.

What does a compiler do, in five words?
Turns source text into machine code.
Where does arithmetic actually happen — memory or registers?
Registers (the tiny fast slots inside the CPU).
Why is a load/store between memory and register costly?
Registers are inside the CPU and fast; memory is off to the side and slow, so crossing takes time.
Compile time vs run time — one-line difference?
Compile time is while translating (no run yet); run time is while the finished program executes.
Warnings are static or dynamic?
Static — found by reading the code at compile time, no run needed.
Sanitizers are static or dynamic?
Dynamic — the running program watches itself at run time.
What is Undefined Behaviour?
An illegal action the language rulebook leaves unspecified, so anything may happen.
Why can UB make -O2 differ from -O0?
The optimizer is allowed to assume UB never happens; if it does, that assumption breaks and the code can diverge.
What is a redzone in ASan?
A forbidden strip of poisoned bytes around each array; touching it means out-of-bounds.
What is shadow memory?
A side table storing, per 8 bytes, whether that memory is OK or poisoned to touch.
What does -g add and who uses it?
Debug info mapping instructions back to source lines; used by the debugger.
Why must -fsanitize go in both CFLAGS and LDFLAGS?
The compiler instruments the code and the linker must attach the sanitizer runtime library.