0

I have a segfault occurring when trying to downcast a std::shared_ptr using std::static_pointer_cast, where the derived class also contains a std::weak_ptr.

Here is a MWE:

#include<iostream>                                                                                                                                                                                                  
#include<memory>                                                                                                                                                                                                    

struct Base {};                                                                                                                                                                                                     

struct Derived : Base                                                                                                                                                                                               
{                                                                                                                                                                                                                   
    std::weak_ptr<int> wp;                                                                                                                                                                                          
};                                                                                                                                                                                                                  

int main()                                                                                                                                                                                                          
{                                                                                                                                                                                                                   
    auto pB = std::make_shared<Base>();              // Create a pointer to Base class instance                                                                                                                     
    auto pD = std::static_pointer_cast<Derived>(pB); // Downcast this to a Derived class instance                                                                                                                   
    auto pint = std::make_shared<int>(0);            // Define a pointer to an integer                                                                                                                              

    std::cout << "assigning pint" << std::endl;                                                                                                                                                                     
    pD->wp = pint;                                   //Attempt to assign member of Derived                                                                                                                                                                 
    std::cout << "Did not segfault" << std::endl;                                                                                                                                                                   

    return 0;                                                                                                                                                                                                       
}
  • 3
    Your `static_pointer_cast` has undefined behaviour, of course, since `pB` does not actually point to an object of type `pD`. – Kerrek SB Dec 15 '16 at 17:38
  • I see. I have clearly misunderstood what the role of `std::static_pointer_cast` is. How would you suggest I achieve what I want, which is to 'upgrade' the underlying `Base` to a `Derived`, yielding a `std::shared_ptr` at the end? – William Handley Dec 15 '16 at 18:01
  • The problem is that you are actually constructing a `Base`, so when you cast it to `Derived` (which works) you get undefined behavior when accessing it since memory for `Derived` was never actually allocated. In this case, you get a segfault. – Donnie Dec 15 '16 at 18:06
  • indeed, although I wasn't sure given that it was referring to `boost::shared_ptr`s – William Handley Dec 15 '16 at 18:15
  • @WilliamHandley: "*I have clearly misunderstood what the role of std::static_pointer_cast is.*" FYI: the point of `static_pointer_cast` is to do exactly what `static_cast` would have done, if you were using a non-smart pointer. So if `Base *pB = new Base; Derived *pD = static_cast(pB)` would not be legal (and it isn't), then neither will the `shared_ptr` equivalent. – Nicol Bolas Dec 15 '16 at 18:28

1 Answers1

0

This compiles and works, but I'm not sure whether it is 'good' c++11

#include<iostream>                                                                                                                                                                               
#include<memory>                                                                                                                                                                                 

struct Base {};                                                                                                                                                                                  

struct Derived : Base                                                                                                                                                                            
{                                                                                                                                                                                                
    Derived(std::shared_ptr<Base> b) : Base{*b} {}                                                                                                                                               
    std::weak_ptr<int> wp;                                                                                                                                                                       
};                                                                                                                                                                                               

int main()                                                                                                                                                                                       
{                                                                                                                                                                                                
    auto pB = std::make_shared<Base>();              // Create a pointer to Base class instance                                                                                                  
    auto pD = std::make_shared<Derived>(pB);                                                                                                                                                     
    auto pint = std::make_shared<int>(0);            // Define a pointer to an integer                                                                                                           

    std::cout << "assigning pint" << std::endl;                                                                                                                                                  
    pD->wp = pint;                                                                                                                                                                               
    std::cout << "Did not segfault" << std::endl;                                                                                                                                                

    return 0;                                                                                                                                                                                    
}