C++26: Standard Library Hardening Experiments
In 2026, the term "hardening" is widely used in the C++ community. This article delves into what this term signifies and presents several core examples. Can a hardened library render C++ fully secure? Let's investigate. When introduced to std::vector, students often recall accessing an element at the i-th position using at least two expressions: [] and .at().
The former is unchecked, potentially leading to undefined behavior if the access is invalid, whereas .at() may throw std::out_of_range, ensuring well-defined behavior. In C++26, the Standard introduces hardened implementations. The status of a standard-library implementation being hardened, and how to enable this mode, is implementation-defined.
For std::vector T, Allocator ::operator[](size_type pos): In essence, activating this "hardened" mode results in well-specified errors/violations instead of undefined behavior.
To clarify the terminology and common queries: At the time of writing (August 2026), compiler and library vendors are finalizing the C++26 feature. The options below represent current vendor hardening mechanisms and may not constitute complete implementations of P3471/P3697/P3878. The following papers form the basis of the feature in C++26: To define hardening in the Standard, this proposal introduces hardened preconditions.
A hardened precondition triggers a contract violation in a hardened implementation. Enhancing the library with hardening primarily involves converting specific preconditions into hardened preconditions in the specification. Which conditions are candidates for hardened implementations? Violations result in memory safety issues, like out-of-bounds access or access to uninitialized memory.
The calling function has all necessary data for the check. The check can be performed in constant time with relatively low overhead. A summary table at cppreference.com outlines all conditions and standard library types. For "Functions with hardened preconditions," see https://en.cppreference.com/cpp/standard_library.
We begin with a simple "hello world" example, observing default compiler behavior and how it changes with hardening options. Running on GCC 16.1 with only -std=c++26 and inputting 100000 yields: Is GCC 16.1 already hardened by default? With GCC 16.1, explicit hardening enablement isn't required in an unoptimized build. However, when optimization is enabled, assertions are disabled by default.
Compiling with -O2 results in: Thus, without optimizations, some runtime checks may already be enabled by default. Enabling hardened mode in an optimized GCC build requires specifying: -std=c++26 -O2 -D_GLIBCXX_ASSERTIONS. Clang Trunk displays the following: Note: libc++ offers NONE, FAST, EXTENSIVE, and DEBUG hardening modes. I'm using DEBUG here due to its informative diagnostic; libc++ suggests FAST for most production applications.
Would you like more information? The article's extended version details bugs found with hardening enabled, such as calling `std::deque::back()` on an empty container and dereferencing an empty `std::optional`. Check out all Premium benefits here. The text also explores basic assembler outputs and real-world experiments conducted by large companies. Refer to Premium benefits for further details.
Written by urgent.news from Lobsters's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.