C++26: Standard Library Hardening Experiments Last Update: 30 August 2026 C 26: Standard Library Hardening Experiments Table of Contents Hardening seems to be a very popular term in the C++ World in
By Coderz Club · 2026-08-31 · Tags: coding
C++26: Standard Library Hardening Experiments
Last Update: 30 August 2026 C 26: Standard Library Hardening Experiments Table of Contents Hardening seems to be a very popular term in the C++ World in 2026. In this article we ll explore what this word means and see some core examples. Can a hardened library make C++ fully safe? Let s find out. The Core Idea When you learned about std::vector you may remember that you can access an element at the i-th position using at least two expressions: std::vector<int> v { 1, 2, 3, 4 }; v[i] = 10; // for some i v.at(j) = 11; // for some j The main difference between those two is that [] is unchecked (and can generate undefined behaviour if you try to access an element which is not there), while .at() may throw std::out_of_range (so it s a well defined behaviour). C++26 Changes In C++26, the Standard introduces the notion of a hardened implementation. Whether a standard-library implementation is hardened, and how that mode is enabled, is implementation-defined. For std::vector<T, Allocator>::operator[](size_type pos): C++ Standard Condition until C++26 If pos < size() is false, the behavior is undefined. since C++26 If pos < size() is false: If the implementation is hardened, a contract violation occurs, If the implementation is not hardened, the behavior is undefined. In other words, if you switch this hardened mode you ll get some well specified error/violation rather than just an undefined behaviour. Let s untangle the wording and common questions: For .at() you may get an exception so why do we need a new alternative? That s fair question. In short at() and [] has different interfaces and performance/error-handling approaches. What s more important you cannot turn exceptions off easily (you can, and std::terminate will be called, but that s not very flexible). So Hardening does not change operator[] into at() - it detects a programming error and terminates instead of allowing memory-unsafe undefined behaviour. A contract violation occurs - this is the key thing here. The hardening feature is expressed in terms of Contracts that also were accepted into C++26. C++26 specifies hardened preconditions using the new Contracts model: violating one in a hardened implementation causes a contract violation evaluated with a terminating semantic. However, a library implementation does not necessarily implement these checks using the actual pre, post, or contract_assert language syntax. So what is this contract violation? Ordinary C++26 Contracts may use ignore, observe, enforce, or quick-enforce semantics. Hardened Standard Library preconditions are more restrictive: in a hardened implementation they must use a terminating semantic, so execution cannot continue after a failed check. It s implementation dependent on how to switch between those modes. Read more here: Contract assertions (since C++26) - cppreference.com Does it work in runtime? Yes, actually it can run in constant expressions, but, more importantly, it runs at runtime. How does this relate to things like GLIBCXX_ASSERTIONS, _ITERATOR_DEBUG_LEVEL and others? C++26 tries to bring those vendor specific checkers and create a common, well defined, set of rules. The Main question: How to enable this thing? GCC / libstdc++: _GLIBCXX_ASSERTIONS enables lightweight Standard Library precondition checks. GCC s broader -fhardened option enables it automatically together with other security options. Clang / libc++: use _LIBCPP_HARDENING_MODE, with NONE, FAST, EXTENSIVE, and DEBUG modes. MSVC STL: _MSVC_STL_HARDENING=1 enables hardening globally. Individual types can be controlled with macros such as _MSVC_STL_HARDENING_VECTOR and _MSVC_STL_HARDENING_OPTIONAL. Note: At the time of writing (August 2026), compiler and library vendors are still completing the C++26 feature. The options below are the current vendor hardening mechanisms and do not necessarily represent complete implementations of P3471/P3697/P3878 Core documents and proposals We have the following papers that make the whole feature, as of C++26: P3471 - main Standard library hardening P3697 - Minor additions to C++26 standard library hardening - basic_stacktrace, shared_ptr<T[N]>, view_interface (front, back), counted_iterator, common_iterator P3878 - Standard library hardening should use a terminating semantic. Ensures that a hardened-precondition violation cannot simply be observed and then continue into the UB that hardening was intended to prevent. Hardening Modes — libc++ documentation To specify hardening in the Standard, this proposal introduces the notion of a hardened precondition. A hardened precondition is a precondition that results in a contract violation in a hardened implementation. Adding hardening to the library largely consists of turning some of the existing preconditions into hardened preconditions in the specification. What conditions are candidates to get the hardened implementation? Violating the precondition results in a memory safety issue (a
Last Update: 30 August 2026 C 26: Standard Library Hardening Experiments Table of Contents Hardening seems to be a very popular term in the C++ World in 2026. In this article we ll explore what this word means and see some core examples. Can a hardened library make C++ fully safe? Let s find out. The Core Idea When you learned about std::vector you may remember that you can access an element at the i-th position using at least two expressions: std::vector<int> v { 1, 2, 3, 4 }; v[i] = 10; // for some i v.at(j) = 11; // for some j The main difference between those two is that [] is unchecked (and can generate undefined behaviour if you try to access an element which is not there), while .at() may throw std::out_of_range (so it s a well defined behaviour). C++26 Changes In C++26, the Standard introduces the notion of a hardened implementation. Whether a standard-library implementation is hardened, and how that mode is enabled, is implementation-defined. For std::vector<T, Allocator>::operator[](size_type pos): C++ Standard Condition until C++26 If pos < size() is false, the behavior is undefined. since C++26 If pos < size() is false: If the implementation is hardened, a contract violation occurs, If the implementation is not hardened, the behavior is undefined. In other words, if you switch this hardened mode you ll get some well specified error/violation rather than just an undefined behaviour. Let s untangle the wording and common questions: For .at() you may get an exception so why do we need a new alternative? That s fair question. In short at() and [] has different interfaces and performance/error-handling approaches. What s more important you cannot turn exceptions off easily (you can, and std::terminate will be called, but that s not very flexible). So Hardening does not change operator[] into at() - it detects a programming error and terminates instead of allowing memory-unsafe undefined behaviour. A contract violation occurs - this is the key thing here. The hardening feature is expressed in terms of Contracts that also were accepted into C++26. C++26 specifies hardened preconditions using the new Contracts model: violating one in a hardened implementation causes a contract violation evaluated with a terminating semantic. However, a library implementation does not necessarily implement these checks using the actual pre, post, or contract_assert language syntax. So what is this contract violation? Ordinary C++26 Contracts may use ignore, observe, enforce, or quick-enforce semantics. Hardened Standard Library preconditions are more restrictive: in a hardened implementation they must use a terminating semantic, so execution cannot continue after a failed check. It s implementation dependent on how to switch between those modes. Read more here: Contract assertions (since C++26) - cppreference.com Does it work in runtime? Yes, actually it can run in constant expressions, but, more importantly, it runs at runtime. How does this relate to things like GLIBCXX_ASSERTIONS, _ITERATOR_DEBUG_LEVEL and others? C++26 tries to bring those vendor specific checkers and create a common, well defined, set of rules. The Main question: How to enable this thing? GCC / libstdc++: _GLIBCXX_ASSERTIONS enables lightweight Standard Library precondition checks. GCC s broader -fhardened option enables it automatically together with other security options. Clang / libc++: use _LIBCPP_HARDENING_MODE, with NONE, FAST, EXTENSIVE, and DEBUG modes. MSVC STL: _MSVC_STL_HARDENING=1 enables hardening globally. Individual types can be controlled with macros such as _MSVC_STL_HARDENING_VECTOR and _MSVC_STL_HARDENING_OPTIONAL. Note: At the time of writing (August 2026), compiler and library vendors are still completing the C++26 feature. The options below are the current vendor hardening mechanisms and do not necessarily represent complete implementations of P3471/P3697/P3878 Core documents and proposals We have the following papers that make the whole feature, as of C++26: P3471 - main Standard library hardening P3697 - Minor additions to C++26 standard library hardening - basic_stacktrace, shared_ptr<T[N]>, view_interface (front, back), counted_iterator, common_iterator P3878 - Standard library hardening should use a terminating semantic. Ensures that a hardened-precondition violation cannot simply be observed and then continue into the UB that hardening was intended to prevent. Hardening Modes — libc++ documentation To specify hardening in the Standard, this proposal introduces the notion of a hardened precondition. A hardened precondition is a precondition that results in a contract violation in a hardened implementation. Adding hardening to the library largely consists of turning some of the existing preconditions into hardened preconditions in the specification. What conditions are candidates to get the hardened implementation? Violating the precondition results in a memory safety issue (a