Lifetime Safety Analysis — Clang 23.0.0git documentation
Clang 23.0.0git documentation
Lifetime Safety Analysis
« Thread Safety Analysis<br>::<br>Contents<br>::<br>C++ Safe Buffers »
Lifetime Safety Analysis¶
Introduction¶
Clang Lifetime Safety Analysis is a C++ language extension which warns about<br>potential dangling pointer defects in code. The analysis aims to detect<br>when a pointer, reference or view type (such as std::string_view) refers to an object<br>that is no longer alive, a condition that leads to use-after-free bugs and<br>security vulnerabilities. Common examples include pointers to stack variables<br>that have gone out of scope, pointers to heap objects that have been<br>freed, fields holding views to stack-allocated objects (dangling-field),<br>returning pointers/references to stack variables (return stack address) or<br>iterators into container elements invalidated by container operations (e.g.,<br>std::vector::push_back)
The analysis design is inspired by Polonius, the Rust borrow checker,<br>but adapted to C++ idioms and constraints, such as the lack of exclusivity enforcement (alias-xor-mutability).<br>Further details on the analysis method can be found in the RFC on Discourse.
This is compile-time analysis; there is no run-time overhead.<br>It tracks pointer validity through intra-procedural data-flow analysis. While it does<br>not require lifetime annotations to get started, in their absence, the analysis<br>treats function calls optimistically, assuming no lifetime effects, thereby potentially missing dangling pointer issues. As more functions are annotated<br>with attributes like clang::lifetimebound, gsl::Owner, and<br>gsl::Pointer, the analysis can see through these lifetime contracts and enforce<br>lifetime safety at call sites with higher accuracy. This approach supports<br>gradual adoption in existing codebases.
Note
This analysis is designed for bug finding, not verification. It may miss some<br>lifetime issues and can produce false positives. It does not guarantee the<br>absence of all lifetime bugs.
Getting Started¶
#include<br>#include
void simple_dangle() {<br>std::string_view v;<br>std::string s = "hello";<br>v = s; // warning: object whose reference is captured does not live long enough<br>} // note: destroyed here<br>std::cout v; // note: later used here
This example demonstrates<br>a basic use-after-scope bug. The std::string_view object v holds a<br>reference to s, a std::string. The lifetime of s ends at the end of<br>the inner block, causing v to become a dangling reference.<br>The analysis flags the assignment v = s as defective because s is<br>destroyed while v is still alive and points to s, and adds a note<br>to where v is used after s has been destroyed.
Running The Analysis¶
To run the analysis, compile with the -Wlifetime-safety-permissive flag, e.g.
clang -c -Wlifetime-safety-permissive example.cpp
This flag enables a core set of lifetime safety checks. For more fine-grained<br>control over warnings, see Warning flags.
Lifetime Annotations¶
While lifetime analysis can detect many issues without annotations, its<br>precision increases significantly when types and functions are annotated with<br>lifetime contracts. These annotations clarify ownership semantics and lifetime<br>dependencies, enabling the analysis to reason more accurately about pointer<br>validity across function calls.
Owner and Pointer Types¶
Lifetime analysis distinguishes between types that own the data they point to<br>(Owners) and types that are non-owning views or references to data owned by<br>others (Pointers). This distinction is made using GSL-style attributes:
[[gsl::Owner]]: For types that manage the lifetime of a resource,<br>like std::string, std::vector, std::unique_ptr.
[[gsl::Pointer]]: For non-owning types that borrow resources,<br>like std::string_view, or raw pointers (which are<br>implicitly treated as pointers).
Many common STL types, such as std::string_view and container iterators,<br>are automatically recognized as Pointers or Owners. You can annotate your own<br>types using these attributes:
#include<br>#include
// Owner type<br>struct [[gsl::Owner]] MyObj {<br>std::string Data = "Hello";<br>};
// View type<br>struct [[gsl::Pointer]] View {<br>std::string_view SV;<br>View() = default;<br>View(const MyObj& O) : SV(O.Data) {}<br>void use() const {}<br>};
void test() {<br>View v;<br>MyObj o;<br>v = o; // warning: object whose reference is captured does not live long enough<br>} // note: destroyed here<br>v.use(); // note: later used here
Without these annotations, the analysis may not be able to determine whether a<br>type is owning or borrowing, which can affect analysis precision. For more<br>details on these attributes, see the Clang attribute reference for<br>gsl::Owner and<br>gsl::Pointer.
Note
Types with mixed ownership semantics (owning some data while holding views to<br>other data) or types with multiple view fields with different lifetimes should<br>not be annotated. The analysis does not yet support expressing such nuanced<br>lifetime relationships.<br>Future enhancements, such as named lifetimes, may provide better support...