On Tue, 16 Jul 2024 at 19:12, Jonathan Wakely <[email protected]> wrote:
>
>
>
> On Tue, 16 Jul 2024, 18:51 M.C.A. (Marco) Devillers via Gcc,
> <[email protected]> wrote:
>>
>> Document number: SCF4C++00
>> Date: 2024-7-16
>> Audience: GCC email list
>> Reply-to: [email protected], [email protected]
>>
>> 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.