Consider the following code (godbolt link):
#include <format>
#include <iostream>
#pragma pack(push)
#pragma pack(1)
struct A {
long l;
int n;
char c;
};
#pragma pack(pop)
int main() {
A arr[] = {{42, 42, 42}, {42, 42, 42}};
std::cout << std::format("{} {} {}", arr[0].l, arr[0].n, arr[0].c); // ok
std::cout << std::format("{} {} {}", arr[1].l, arr[1].n, arr[1].c); // error
}
The compile command is as follows:
clang-19 -std=c++23 -stdlib=libc++ -O3 -fsanitize=undefined
The runtime error is as follows:
runtime error: reference binding to misaligned address 0x7ffc995b2f3d for type 'long', which requires 8 byte alignment.
Why does std::format
require its arguments are aligned?
std::format takes its arguments by reference, and UB sanitizer detects it as UB because it will crash on platforms where the CPU cannot automatically fix unaligned loads and stores. see Load of misaligned address and UBsan finding
to fix the code you can pass temporaries to std::format
instead
std::cout << std::format("{} {} {}", long{arr[0].l}, int{arr[0].n}, char{arr[0].c}); // ok
std::cout << std::format("{} {} {}", long{arr[1].l}, int{arr[1].n}, char{arr[1].c}); // ok
this is telling the compiler to create a temporary before passing it to the function, and this temporary should be aligned.