Case 42: Type Alignment Changed (standalone alignas)¶
| Field | Value |
|---|---|
| Verdict | ๐ด BREAKING |
| Category | Breaking |
| Platforms | Linux, macOS |
| Flags | ABI break, API break |
Detected ChangeKinds |
โ |
| Source files | browse on GitHub |
Category: Type Layout / DWARF | Verdict: BREAKING
What this case is about¶
v1 defines CacheBlock with aligned(8). v2 increases alignment to
aligned(64) for cache-line optimization. The fields and their types are
identical โ only the alignment attribute changes.
This is a clean, isolated alignment change (unlike case41 which bundles alignment with type removal and enum changes).
What breaks at binary level¶
- sizeof may change: Compilers pad structs to a multiple of their alignment.
aligned(64)makessizeof(CacheBlock)= 64 (padded to alignment boundary). Withaligned(8)it's also 64 here, but the ABI contract about where the struct can live in memory changes. - Stack allocation misaligned: Old binaries allocate
CacheBlockwith 8-byte alignment. The v2 library may use SIMD instructions (e.g.,vmovdqa) that require 64-byte alignment โ SIGBUS / SIGSEGV. - Array stride changes: If sizeof changes,
&blocks[i]computes wrong offsets. - malloc alignment:
malloctypically returns 16-byte aligned memory. 64-byte aligned structs needaligned_alloc(64, sizeof(CacheBlock)).
What abicheck detects¶
TYPE_ALIGNMENT_CHANGED: Detected via DWARFDW_AT_alignmentor inferred fromDW_AT_byte_sizechanges caused by alignment padding.
Overall verdict: BREAKING
How to reproduce¶
gcc -shared -fPIC -g bad.c -include bad.h -o libbad.so
gcc -shared -fPIC -g good.c -include good.h -o libgood.so
python3 -m abicheck.cli dump libbad.so -o /tmp/v1.json
python3 -m abicheck.cli dump libgood.so -o /tmp/v2.json
python3 -m abicheck.cli compare /tmp/v1.json /tmp/v2.json
# โ BREAKING: TYPE_ALIGNMENT_CHANGED
How to fix¶
Use opaque types so callers never allocate or embed the struct directly:
/* header */
typedef struct CacheBlock CacheBlock;
CacheBlock* block_alloc(void); /* library controls alignment */
/* implementation */
struct CacheBlock __attribute__((aligned(64))) { ... };
CacheBlock* block_alloc(void) {
return aligned_alloc(64, sizeof(CacheBlock));
}
Real-world examples¶
- DPDK packet buffers require cache-line alignment (64 bytes).
- Intel TBB / oneTBB uses
alignas(64)for scalable allocator metadata. - Changing alignment in a public struct after release broke ABI in several multimedia libraries (FFmpeg, GStreamer).
References¶
Source files¶
See also: Examples overview ยท All BREAKING cases ยท Category: Breaking.