On Tue, 16 Jul 2024 at 19:12, Jonathan Wakely <jwakely....@gmail.com> wrote: > > > > On Tue, 16 Jul 2024, 18:51 M.C.A. (Marco) Devillers via Gcc, > <gcc@gcc.gnu.org> wrote: >> >> Document number: SCF4C++00 >> Date: 2024-7-16 >> Audience: GCC email list >> Reply-to: marco.devill...@gmail.com, gcc@gcc.gnu.org >> >> I. Introduction >> >> Because C++ smart pointers are based on RAII it is easy to trigger an >> overflow of the C stack since destructors call each other. Smart >> pointers are supposed to be safe, smart pointers are likely to be used >> extensively in the future, and this behaviour could make a large >> number of C++ programs core dump unexpectedly. >> This proposal is to remove this behaviour from GCCs standard library > > > Where does it exist in the library? > > The problem in your program is easily avoided, without changing the standard > or GCC's implementation of the standard library. > >> and also showcases a small trick by which that can be done. >> >> II. Motivation and Scope >> >> We all want smart pointers since they allow for easy and safe memory >> management, this desire is only expected to increase over the >> following decades. >> >> However due to RAII semantics it's easy to trigger an overflow of the >> C stack once garbage goes out of scope. Observe the following trivial >> program: >> >> #include <iostream> >> #include <memory> >> >> struct list_node { >> using ptr = std::unique_ptr<list_node>; >> ~list_node() { >> } >> >> int x; >> ptr next; >> }; >> >> int main() { >> list_node::ptr next = nullptr; >> >> for(int i = 0; i < 100000; ++i) { // decrease value to see it not segfault >> next = list_node::ptr(new list_node{i, std::move(next)}); >> } >> } >> >> Cascading frees will make this program core dump depending the size of >> the list. Please note, that that program will segfault on for current >> data-driven days relatively tiny sizes. > > > So don't do that then. It's easy to add a loop to clean up the list. Or > create an actual list class to manage the nodes and do that loop in its > destructor. Nobody is forced to define a list only in terms of nodes, rather > than a list class that manages the nodes.
Or you can put the loop in the node destructor: ~list_node() { while (next) next = std::move(next->next); } Unlike your cleanup stack, this doesn't require any additional memory allocation or synchronization.