【问题标题】:Is this some sort of pointer error?这是某种指针错误吗?
【发布时间】:2017-04-17 23:27:02
【问题描述】:

我在空闲时间开发一个小游戏,在编写代码时遇到了一个问题。

我已经隔离了这个问题,并在此处尽可能小:

#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;
}

当来回按“1”和“2”时,有时它似乎可以工作,当我退出时,我得到类似 -1073741510 或类似返回值的东西。在我的游戏代码中,它似乎也经常崩溃。

(退出我的意思是使用命令窗口上的 X 按钮,抱歉没有澄清)

在对 unique_ptr 和一般指针以及多态类进行了一些研究之后,我仍然不明白为什么会这样。

那么,这里发生了什么?

【问题讨论】:

  • 定义“退出”。显示的代码没有提供干净地终止程序的方法。它在无限循环中运行。
  • @SamVarshavchik 已修复,抱歉没有澄清

标签: c++ class pointers crash polymorphism


【解决方案1】:

您正在从堆栈变量创建 shared_ptr。这最终会在 p 上调用 delete ,这是不安全的。见Calling delete on variable allocated on the stack

编辑: 您需要使 p 成为指针。您可以执行以下操作:

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};
    }
};

【讨论】:

  • 您需要将 p 设为指针。您可以执行以下操作:class Base { public: std::shared_ptr&lt;std::string&gt; p; virtual ~Base() {} virtual std::vector&lt;std::shared_ptr&lt;std::string&gt;&gt; getText() = 0; }; class Derived1 : public Base { public: Derived1() { p = std::make_shared&lt;std::string&gt;("from1"); } std::vector&lt;std::shared_ptr&lt;std::string&gt;&gt; getText() { return std::vector&lt;std::shared_ptr&lt;std::string&gt;&gt;{p}; } };
  • 是的,有办法。请参阅shared_ptr 的文档。
  • 它不是堆栈变量。然而,它是一个成员变量,由包含它的完整对象拥有,并且安排一个 shared_ptr 将它粉碎成碎片会让真正的所有者非常非常疯狂。
  • 你是对的。我很着急,应该在我第一次回答之前完整阅读代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-03
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
相关资源
最近更新 更多