Skip to main content

Module 2: Memory, Pointers & Machine Representation: Case Studies

These case studies make pointer bugs and representation bugs visible before they become folklore.


Case Study 1: Use-After-Free In A Cache

Scenario: A cache returns a pointer to an entry. Another path evicts and frees the entry. The caller later dereferences the dangling pointer.

Source anchor: Clang's AddressSanitizer documents detection of use-after-free and related memory errors.

Module concepts: heap, ownership, dangling pointer, ASan.

Wrong Approach

"The pointer value still looks valid."

Better Approach

Define ownership:

borrowed pointer:
valid only while cache lock/lease held

owned copy:
caller must free

handle/id:
lookup each use

Tradeoff Table

ChoiceGainCost
Return raw internal pointerFast accessLifetime is easy to violate
Borrowed-pointer contractClearer ownership rulesRequires lock or lease discipline
Copy or handle-based APISafer lifetime boundaryMore lookup or allocation overhead

Failure Mode

Tests pass under light usage, but eviction on another path frees the object and later reads become intermittent crashes or corrupt results.

Required Artifact

Write an ASan reproduction and an ownership contract for the cache API.

Project / Capstone Connection

Use this ownership language in any allocator, cache, or shared-buffer subsystem built later in systems work.


Case Study 2: Buffer Overflow Detected By Valgrind

Scenario: A parser allocates bytes and writes + 1 to append a terminator.

Source anchor: Valgrind Memcheck documents how it reports invalid reads, writes, and leaks in C and C++ programs.

Module concepts: heap allocation, bounds, terminator, Valgrind.

Wrong Approach

Forget that strings need room for '\0'.

Better Approach

Allocate and test explicitly:

char *s = malloc(len + 1);
memcpy(s, input, len);
s[len] = '\0';

Tradeoff Table

ChoiceGainCost
Allocate exact payload lengthMinimal memory useNo room for terminator
Allocate len + 1Correct C-string layoutMust reason about overflow on size math
Higher-level buffer helperReusable safetyMore abstraction and API surface

Failure Mode

The extra terminator write lands one byte past the allocation, producing small corruptions that may surface only under tooling or unrelated code changes.

Required Artifact

Run or mock a Memcheck report and explain the invalid write.

Project / Capstone Connection

Apply this allocation rule to parsers, tokenizers, and serialization helpers that materialize C strings.


Case Study 3: Endianness Breaks Binary File Format

Scenario: A program writes an integer directly with fwrite(&x, sizeof x, 1, f). The file is read on another architecture and values are wrong.

Source anchor: Machine representation and serialization require a byte-order contract; network byte order functions provide a practical reference. See byteorder(3).

Module concepts: endianness, serialization, integer width.

Wrong Approach

"Bytes on my machine are the format."

Better Approach

Define format:

field width:
uint32_t

byte order:
big-endian/network order

version:
header magic + format version

Tradeoff Table

ChoiceGainCost
Dump native integer bytesFast to implementNon-portable across architectures
Fixed-width explicit byte orderPortable and testableRequires encode/decode code
Text serializationHuman-readableLarger and slower

Failure Mode

Files look correct on the authoring machine, then decode into nonsensical values or version mismatches on another architecture.

Required Artifact

Write a binary format spec with byte offsets and endianness.

Project / Capstone Connection

Use this format discipline for binary logs, caches, and protocol exercises later in the program.


Case Study 4: Struct Padding Over The Wire

Scenario: A network protocol sends sizeof(struct Message) bytes. Another compiler lays out padding differently.

Source anchor: C object representation and alignment rules make raw structs unsafe as portable wire formats.

Module concepts: struct layout, padding, alignment, packed formats.

Wrong Approach

Use raw in-memory structs as protocol messages.

Better Approach

Serialize fields explicitly:

offset 0: uint16_t type
offset 2: uint32_t length
offset 6: payload bytes

Tradeoff Table

ChoiceGainCost
Send raw struct bytesVery little codePadding, alignment, and ABI coupling
Explicit field serializationStable wire formatMore encode/decode work
Packed struct shortcutsSmaller apparent diffCan still hide portability and alignment issues

Failure Mode

One build inserts padding or changes alignment, so peer systems misread fields even though each side's local tests pass.

Required Artifact

Draw struct layout with padding and a separate wire layout.

Project / Capstone Connection

Carry this distinction into socket protocols, file headers, and IPC message formats.


Case Study 5: Floating-Point Equality In Money-Like Calculation

Scenario: A program sums decimal prices in double and checks equality against an expected total.

Source anchor: IEEE 754 floating point representation explains rounding and special values; use compiler or runtime examples to inspect binary approximation.

Module concepts: floating point, rounding, binary representation, fixed-point.

Wrong Approach

Compare decimal money with exact double equality.

Better Approach

Use integer cents or decimal type:

int64_t cents = 1299;

For measurement values, compare within tolerance.

Tradeoff Table

ChoiceGainCost
double equality for moneySimple codeRounding mismatch and unstable comparisons
Integer centsExact for fixed decimal scaleRequires explicit scaling and formatting
Tolerance-based compareWorks for measurementsNot appropriate for exact financial totals

Failure Mode

An apparently exact total fails equality checks because decimal fractions such as 0.1 are represented approximately in binary.

Required Artifact

Write a representation note showing why 0.1 + 0.2 is not exact in binary floating point.

Project / Capstone Connection

Use this choice framework when later projects need counters, pricing-like values, or scientific measurements with different precision rules.


Source Map

SourceUse it for
AddressSanitizerdetecting use-after-free and memory errors
Valgrind Memcheckinvalid reads/writes and leaks
byteorder(3)network byte order
cppreference fixed-width integersinteger widths

Completion Standard

  • At least three artifacts are completed.
  • At least one artifact includes ASan or Valgrind evidence.
  • At least one artifact defines a byte-level format.