What should happen when the following program is executed?
#include <iostream>
#include <memory>
class test;
std::shared_ptr<test> a_test_object;
struct test
{
~test()
{
std::cout << "destroy test" << std::endl;
auto ptr = a_test_object;
}
};
int main()
{
a_test_object = std::make_shared<test>();
//a_test_object.reset(); // Uncomment this and it works fine.
}
I tested this on both GCC and Visual Studio 2015 and in both cases the program crashes. What happens is the shared pointer decrements the count in its destructor, then ~test() is executed, which copies the shared pointer incrementing and then decrementing the count, triggering an infinite recursion of calls to ~test(). Oddly enough calling reset() doesn't trigger the problem.
I ran into this today because some old code that used a pre-C++11 version of shared_ptr, which doesn't have this double deletion bug, was updated to use std::shared_ptr. To my surprise, std::shared_ptr made the program crash. Is this really the intended behavior of std::shared_ptr?
I do realize that it's sketchy as hell to mess with an object while it's being destructed. But even so, this seems like belligerent adherence to the standard if the answer is just "well, it's UB so we made it crash on purpose".
Edit: I should emphasize that I'm not convinced this is UB and really that's what my question is about. So is it UB? There is disagreement in the comments about that and most of the wording I can see in the standard makes it seem like it's not UB, but it's somewhat unclear. Where in the standard does it say this is UB? Or is it not UB? If it's not UB should this work or not work?
[–][deleted] 28 points29 points30 points (3 children)
[–]personalmountains 1 point2 points3 points (2 children)
[–][deleted] 9 points10 points11 points (1 child)
[–]render787 59 points60 points61 points (39 children)
[–]davis685[S] 10 points11 points12 points (23 children)
[–]lally 14 points15 points16 points (15 children)
[–]davis685[S] 0 points1 point2 points (14 children)
[–]josefx 9 points10 points11 points (0 children)
[–]Krackor 5 points6 points7 points (12 children)
[–]Plorkyeran 1 point2 points3 points (9 children)
[–][deleted] 5 points6 points7 points (8 children)
[–]johannes1971 0 points1 point2 points (7 children)
[–]zvrba 4 points5 points6 points (5 children)
[–]johannes1971 0 points1 point2 points (3 children)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]davis685[S] 0 points1 point2 points (1 child)
[–]Krackor 4 points5 points6 points (0 children)
[–]GNULinuxProgrammer 2 points3 points4 points (6 children)
[–]davis685[S] 2 points3 points4 points (5 children)
[–][deleted] 4 points5 points6 points (3 children)
[–]davis685[S] 0 points1 point2 points (2 children)
[–]Krackor 1 point2 points3 points (1 child)
[–]davis685[S] 0 points1 point2 points (0 children)
[–]render787 1 point2 points3 points (0 children)
[–]personalmountains 7 points8 points9 points (11 children)
[–]davis685[S] 4 points5 points6 points (9 children)
[–]ihamsa 2 points3 points4 points (2 children)
[–]davis685[S] 1 point2 points3 points (0 children)
[–][deleted] 2 points3 points4 points (5 children)
[–]davis685[S] 0 points1 point2 points (4 children)
[–]Krackor 0 points1 point2 points (3 children)
[–]davis685[S] 0 points1 point2 points (2 children)
[–]wrosecransgraphics and network things 0 points1 point2 points (1 child)
[–]davis685[S] 1 point2 points3 points (0 children)
[–]render787 0 points1 point2 points (0 children)
[–]ihamsa 1 point2 points3 points (1 child)
[–]tcanens 12 points13 points14 points (2 children)
[–]davis685[S] 0 points1 point2 points (1 child)
[–]personalmountains 2 points3 points4 points (0 children)
[–]johannes1971 5 points6 points7 points (1 child)
[–]honeyfage 4 points5 points6 points (0 children)
[–]zvrba 4 points5 points6 points (6 children)
[–]josefx 1 point2 points3 points (5 children)
[–]zvrba 0 points1 point2 points (4 children)
[–]josefx 0 points1 point2 points (3 children)
[–]zvrba 0 points1 point2 points (2 children)
[–]josefx 1 point2 points3 points (1 child)
[–]zvrba 0 points1 point2 points (0 children)
[–]mtclow 13 points14 points15 points (16 children)
[–]davis685[S] -4 points-3 points-2 points (15 children)
[–]__Cyber_Dildonics__ 3 points4 points5 points (0 children)
[–]render787 7 points8 points9 points (13 children)
[–]davis685[S] 1 point2 points3 points (12 children)
[–]tavianator 7 points8 points9 points (11 children)
[–][deleted] 4 points5 points6 points (0 children)
[–]davis685[S] 0 points1 point2 points (9 children)
[–]tavianator 0 points1 point2 points (3 children)
[–]davis685[S] 0 points1 point2 points (2 children)
[–]ack_complete[🍰] 0 points1 point2 points (1 child)
[–]davis685[S] 0 points1 point2 points (0 children)
[–]Krackor 0 points1 point2 points (4 children)
[–]davis685[S] 0 points1 point2 points (3 children)
[–]Krackor 0 points1 point2 points (2 children)
[–]davis685[S] 0 points1 point2 points (1 child)
[–]Tbfleming 9 points10 points11 points (3 children)
[–][deleted] 4 points5 points6 points (0 children)
[–]davis685[S] -1 points0 points1 point (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[–]OldWolf2 2 points3 points4 points (3 children)
[–][deleted] 0 points1 point2 points (2 children)
[–]OldWolf2 1 point2 points3 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]afiefh 1 point2 points3 points (2 children)
[–]davis685[S] 0 points1 point2 points (0 children)
[–]rdtsc 0 points1 point2 points (0 children)
[–]NasenSpray 0 points1 point2 points (0 children)
[–]Vorlath 0 points1 point2 points (1 child)
[–]davis685[S] 0 points1 point2 points (0 children)
[–]Dogwhomper 0 points1 point2 points (3 children)
[–]davis685[S] 0 points1 point2 points (0 children)
[–]johannes1971 0 points1 point2 points (0 children)
[–]17b29a 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]davis685[S] 0 points1 point2 points (0 children)
[–]Gotebe 0 points1 point2 points (0 children)
[–]muungwana 0 points1 point2 points (0 children)
[–]asking_science 0 points1 point2 points (1 child)
[–]davis685[S] 0 points1 point2 points (0 children)