C++ 如何防止共享指针的无序映射泄漏?

C++ 如何防止共享指针的无序映射泄漏?,c++,c++11,memory-leaks,shared-ptr,unordered-map,C++,C++11,Memory Leaks,Shared Ptr,Unordered Map,我正在构建一个控制台应用程序,我只使用智能指针。我选择只使用智能指针来学习何时使用哪个智能指针。在这个应用程序中,我尝试使用状态模式在不同的状态之间切换。基类是这个类的TurnState,其他所有状态类都继承它 在gamecontroller中,我定义了当前状态。为了在状态之间切换,我想使用一个无序的_映射,其中enum作为键,state类作为值。但当我写下std::无序地图(unordered\u map)(u turn\u states\u map)时,在标题中,我有一些内存泄漏 为了消除这

我正在构建一个控制台应用程序,我只使用智能指针。我选择只使用智能指针来学习何时使用哪个智能指针。在这个应用程序中,我尝试使用状态模式在不同的状态之间切换。基类是这个类的TurnState,其他所有状态类都继承它

在gamecontroller中,我定义了当前状态。为了在状态之间切换,我想使用一个无序的_映射,其中enum作为键,state类作为值。但当我写下
std::无序地图(unordered\u map)(u turn\u states\u map)时,在标题中,我有一些内存泄漏

为了消除这些内存泄漏,我尝试在解构器中销毁它们,如下所示:

GameController::~GameController()
{
    for (std::unordered_map<TurnStateEnum, std::shared_ptr<TurnState>>::iterator iterator{ _turn_states_map.begin() }; iterator != _turn_states_map.end(); iterator++) {
        iterator->second.reset();
        _turn_states_map.erase(iterator);
    }
    _turn_states_map.clear();
}
在TurnState源下面:

TurnState::TurnState(GameController& gameCtrl) : _gameCtrl ( gameCtrl )
{
}

TurnState::~TurnState()
{
}

void TurnState::next_state(TurnStateEnum stateEnum)
{
    _gameCtrl.set_next_state(stateEnum);
}
除了基类之外,Setup State没有任何其他变量或方法,目前,这些方法是空的


编辑2-最小示例v2

这可能是一个更好的例子。我创建了一个控制台项目并将其上载到:

您的程序中没有漏洞。您正在正确使用
std::shared\u ptr
。没有要修复的循环引用。尽管析构函数是多余的,但它们是无害的

您只是没有使用
\u crtdumpmomeryleaks()
对。在运行
main
中本地对象的析构函数之前调用它。当然,它会将这些对象分配的内存报告为泄漏

要修复:

int main(int argc, const char * argv[])
{
  (
    GameController gameCtrl = GameController();
    gameCtrl.do_action("test");
  }
  _CrtDumpMemoryLeaks();  

  return 0;
}

TurnState
可能有泄漏?@πάνταῥεῖ 我也为此感到害怕。为了测试它,我从TurnState制作了一个共享的\u ptr,它没有泄漏,在超出范围后,它被很好地清理了。智能指针通常被宣传为修复所有内存泄漏的神奇按钮。这与事实相去甚远。正确使用它们确实意味着永远不必担心删除任何东西,关键是“正确”。一般来说,您必须了解智能指针是如何工作的,以及内存是如何工作的。自动范围和动态范围之间的区别。循环引用将是泄漏内存的一种方式,例如,尽管gazoo中有智能指针。你需要花一些时间来整理你的C++书籍,直到你完全了解它们是如何工作的,为什么,以及如何。<代码>后续的
iterator++
表现出未定义的行为。@user3473161
std::weak_ptr
可能有助于找到解决方案。
class GameController;

class TurnState
{
public:
    TurnState(GameController& gameCtrl);
    virtual ~TurnState();

    void next_state(TurnStateEnum stateEnum);
    virtual void do_turn(Socket& client, Player& player, std::string command) = 0;
protected:
    GameController& _gameCtrl;
};
TurnState::TurnState(GameController& gameCtrl) : _gameCtrl ( gameCtrl )
{
}

TurnState::~TurnState()
{
}

void TurnState::next_state(TurnStateEnum stateEnum)
{
    _gameCtrl.set_next_state(stateEnum);
}
int main(int argc, const char * argv[])
{
  (
    GameController gameCtrl = GameController();
    gameCtrl.do_action("test");
  }
  _CrtDumpMemoryLeaks();  

  return 0;
}