0

I'm working on a small game in my free time and while coding it I came across an issue.

I've isolated the issue and made it as small as possible here:

#include <iostream>
#include <memory>
#include <vector>
#include <Windows.h>
class Base
{
public:
    std::string p;
    virtual ~Base()
    {

    }
    virtual std::vector<std::shared_ptr<std::string>> getText() = 0;
};
class Derived1 : public Base
{
public:
    Derived1()
    {
        p = "from1";
    }
    std::vector<std::shared_ptr<std::string>> getText()
    {
        return std::vector<std::shared_ptr<std::string>>{std::shared_ptr<std::string>(&p)};
    }
};
class Derived2 : public Base
{
public:
    Derived2()
    {
        p = "from2";
    }
    std::vector<std::shared_ptr<std::string>> getText()
    {
        return std::vector<std::shared_ptr<std::string>>{std::shared_ptr<std::string>(&p)};
    }
};
int main()
{
    std::unique_ptr<Base> state;
    std::vector<std::shared_ptr<std::string>> displayText;
    state.reset(new Derived1());
    displayText = state->getText();
    while(1)
    {
        for(auto i = displayText.begin(); i != displayText.end(); ++i)
            std::cout << **i;
        if (GetKeyState('2') < 0)
        {
            state.reset(new Derived2());
            displayText.clear();
            displayText = state->getText();
        }
        else if (GetKeyState('1') < 0)
        {
            state.reset(new Derived1());
            displayText.clear();
            displayText = state->getText();
        }
    }
    return 0;
}

When pressing "1" and "2" back and forth it seems to work sometimes, and when I exit out I get something like -1073741510 or similar as the return value. In my game code it also seems to crash a lot.

(By exit out I mean using the X button on the command window, sorry for not clarifying)

After doing some research on unique_ptr and pointers in general along with polymorphic classes I still can't understand why this behaves the way it does.

So, what's going on here?

1 Answers1

0

You are creating a shared_ptr from a stack variable. This will end up calling delete on p which is not safe. See Calling delete on variable allocated on the stack

EDIT: You would need to make p a pointer. You could do something like the following:

class Base
{
public:
    std::shared_ptr<std::string> p;
    virtual ~Base()
    {

    }
    virtual std::vector<std::shared_ptr<std::string>> getText() = 0;
};
class Derived1 : public Base
{
public:
    Derived1()
    {
        p = std::make_shared<std::string>("from1");
    }
    std::vector<std::shared_ptr<std::string>> getText()
    {
        return std::vector<std::shared_ptr<std::string>>{p};
    }
};
class Derived2 : public Base
{
public:
    Derived2()
    {
        p = std::make_shared<std::string>("from2");
    }
    std::vector<std::shared_ptr<std::string>> getText()
    {
        return std::vector<std::shared_ptr<std::string>>{p};
    }
};
Community
  • 1
  • 1
Chris Ray
  • 31
  • 2
  • You would need to make p a pointer. You could do something like the following: `class Base { public: std::shared_ptr p; virtual ~Base() {} virtual std::vector> getText() = 0; }; class Derived1 : public Base { public: Derived1() { p = std::make_shared("from1"); } std::vector> getText() { return std::vector>{p}; } };` – Chris Ray Dec 03 '16 at 01:03
  • Yes, there is a way. See `shared_ptr`'s documentation. – Sam Varshavchik Dec 03 '16 at 01:03
  • 1
    It's not a stack variable. It is, however, a member variable, owned by the complete object that contains it, and arranging for a shared_ptr to smash it to bits is going to make the true owner very very mad. – Ben Voigt Dec 03 '16 at 01:13
  • You are correct. I was in a hurry, and should have read the code fully before my first answer. – Chris Ray Dec 03 '16 at 01:37