C++ is a powerful and widely used programming language known for its flexibility and performance. However, one of its historical drawbacks has been the lack of built-in memory safety features, which can lead to various types of memory-related bugs such as buffer overflows, dangling pointers, and memory leaks.
This is a well-known issue that has persisted for decades, and numerous attempts have been made to address it. Unfortunately, none has provided a complete solution.
What has been done over the years to improve memory safety in the language?
Garbage Collector
A Garbage Collector (GC) is a mechanism used in programming languages and runtime environments to automatically reclaim memory that is no longer in use by the program. Its primary purpose is to manage memory allocation and deallocation, relieving developers from the burden of manual memory management and helping to prevent common memory-related errors such as memory leaks and dangling pointers.
For C++, in 2008 a minimal support for garbage collection and reachability-based leak detection was added to C++0x. Since then, many proposals have been put forward. Unfortunately, none of them has addressed all cases, and the garbage collector was definitively removed in C++23.
Borrow Checkers
The borrow checker is a key feature of the Rust programming language that enforces memory safety and prevents data races by statically analyzing the ownership and borrowing of references in a program at compile time. It is one of Rust's core innovations and a fundamental aspect of its ownership model.
So the question is: Why not bring this mechanism to C++?
In 2021, a Google Chromium team tried to answer this question. In their conclusion paper, they concluded:
It would seem at first glance that we have successfully written C++ borrow checking, with the types defined above. Unfortunately, we have not.
Indeed, as described in their paper, many challenges remained unresolved, and borrow checking ultimately could not be added to C++.
Runtime Checkers
C++ runtime checks encompass various mechanisms and techniques for validating program behavior and detecting errors during execution. In C++, they are called sanitizers. They are part of the Clang and GCC compilers and provide runtime instrumentation to catch errors during program execution. These sanitizers are generally used during development and testing phases to identify and fix issues. However, they are generally not used in production, and many issues that occur in production may not be encountered during development.
Even during development, sanitizers are not universally adopted and therefore are not always used.
What next?
Currently, Stroustrup is working on a potential solution to this safety problem: it's called C++ profiles (that is, a set of rules which, when followed, achieve specific safety guarantees). They would be defined by the ISO C++ standard, addressing common safety issues like pointers and array ranges.
He’s created a GitHub repository, where people can submit suggestions and he can share his drafts, helping build a community that can move this work forward within a reasonable timeframe.
Conclusion
C++ has continued to resist attempts to introduce comprehensive memory safety into the language. However, finding a definitive solution to this significant issue has become increasingly urgent. Perhaps we should consider adding this problem to the Millennium Prize Problems. :)
