How do the malloc debugging environment variables (such as MallocScribble) expose uninitialised and freed memory, and when do they beat ASan?
Predict first
What does a fresh allocation contain when malloc scribbling is switched on?
// === main.swift ===
let p = UnsafeMutablePointer<UInt8>.allocate(capacity: 64)
print("fresh bytes:", (0..<4).map { String(p[$0], radix: 16) }.joined(separator: " "))
- aa aa aa aa
- 0 0 0 0
- 55 55 55 55
Mental model. Painting new rooms bright pink so anyone who walks in without cleaning them is obvious.
The system allocator can be asked to make misuse obvious. MallocScribble=1 fills freed blocks with 0x55 and fresh allocations with 0xaa; MallocPreScribble fills new blocks; MallocGuardEdges puts guard pages around large blocks; and MallocStackLogging (Q457) records allocation stacks. They need no rebuild: set them in the scheme or the shell. In the check, a freshly allocated 64-byte buffer reads aa aa aa aa under MallocScribble=1, so code that reads uninitialised memory suddenly fails in a way that is reproducible instead of sometimes holding zeros.
Use them when you cannot rebuild with ASan (a prebuilt framework, a third-party binary) or when ASan’s cost hides a timing bug. They are much weaker: scribbling only helps when the poisoned value changes behaviour, and guard pages catch overruns only of large blocks. Behaviour of freed small blocks is allocator-dependent (the first bytes may hold allocator metadata), so I only assert the fresh-allocation pattern. For Swift value types you rarely need this; it matters with unsafe pointers and C.
New blocks are filled with 0xaa, freed ones with 0x55.
Common traps
- Leaving the variable set in a shared scheme. It slows allocations for everyone.
- Expecting precise freed-block contents. Rely on ASan for use-after-free.
They might follow up with
- Zombie objects? Objective-C only (Q457).
- Does it change release builds? It applies to any process that inherits the variable.
Related questions
- 23.2.2 What are zombie objects and malloc stack logging, and how do you debug dangling references and over-released…
- 23.3.1 What do the Address, Thread and Undefined Behavior sanitizers catch, what do they cost, and when do you use…
← An app freezes: how do you tell a detected queue deadlock from a real… What does the leaks command-line tool report for a cycle, and how… →