【问题标题】:Is there any memory leak in the function like function(new Foo())?function(new Foo()) 之类的函数中是否存在内存泄漏?
【发布时间】:2015-07-27 07:17:55
【问题描述】:

我最近在写一个分层状态机。我想在过渡到另一个超状态时设置一个初始子状态。

因此我有如下代码来设置初始状态。第一个版本

void Foo::setInitialSubState(State* next_state){
  if(state_)
    delete state_;

  state_ = next_state;
  state_->enter(*this);
}

然后我发现 if(state_) 总是返回 true.. 所以我删除了它。该函数在构造函数 Foo::Foo() 中调用。

Foo::Foo()
{
  setInitialSubState(new State());
}

我想删除 state_ 时出现段错误错误。所以我在构造函数中初始化了成员 var state_。

Foo::Foo()
{
  state_ = 0;
  setInitialSubState(new State());
}

这将解决段故障问题。

我想知道我使用setInitialSubState(new State())时是否有内存泄漏问题?我不知道..如何更改 if(state_) 以避免 delete() 导致段错误?

感谢您的所有善意建议..

----编辑----

为了让自己更清楚地了解内存泄漏部分,我想我可以将问题改写为

 void Foo::setInitialSubState(State* next_state)
{
  state_ = next_state;
  delete state_;
}

Foo::Foo()
{
  state_ = 0;
  setInitialSubState(new State());
}

有没有内存泄漏?

【问题讨论】:

  • 你可以在指向0的指针上调用delete。如果你在随机地址上调用它,可能会导致段错误。始终初始化您的指针。
  • 仍然回答最初的问题,是的,调用new Foo() 在某些情况下会导致内存泄漏(主要是在异常情况下)。
  • 只删除 if(state_) 部分,保留 delete state_ 部分。
  • @Jaciq 这可能会导致未定义的行为。
  • 你为什么不看看std::unique_ptr?

标签: c++ memory-leaks


【解决方案1】:

最初state_ 的未初始化指针有一些值,这就是if(state_) 进入并尝试delete 一些随机指针的原因。

在零指针上调用 delete 是安全的,这就是您的修复工作有效的原因。

关于内存泄漏:如果 Foo 类没有析构函数,那么你可以有一个,但要确保你应该发布更多代码..

【讨论】:

  • Jaciq 发表评论:“随着您的编辑,您将有更多的泄漏,因为现在 state 和 next_state 分配的内存都将丢失。当您通过指针传递时,指针仍然指向到它在函数之外执行的完全相同的内存区域。“是真的吗?我虽然我的编辑和原版是同一个问题...
【解决方案2】:

下面的函数没有做任何事情,你正在删除传递给函数的对象。如果 state_ 之前指向某个东西,那么它会导致内存泄漏。

void Foo::setInitialSubState(State* next_state)
{
  state_ = next_state;  // state_ points to the object that next_state points to.
  delete state_; // deletes what state_ and next_state points to.
}

另一种方法是将 state_ 声明为智能指针,则无需删除该指针

std::unique_ptr<State> state_;

...

void Foo::setInitialSubState(State* next_state)
{
  state_ = std::make_unique<State>(next_state);
}

下面的代码很好,尽管您可能希望使用nullptr 而不是 0 以更清楚地表明state_ 是一个指针,并将其移至初始化列表:

Foo::Foo() : state_(nullptr)
{
  setInitialSubState(new State());
}

【讨论】:

  • 您真的是要使用make_shared 而不是make_unique 吗?如果是这样,您能详细说明一下吗?
  • @tianb03 与其让setInitialSubState taka 成为指针,不如让它接受构造State 对象所需的参数。然后,调用代码将不再显示使用 if new,这可能会避免混淆所有权。无论如何,它实际上是make_shared 的包装器:template &lt;typename ... Args&gt; void Foo::setInitialSubState(Args&amp;&amp; ... args) { _state = make_shared(new State(std::forwards&lt;Args&gt;(args) ...)); }
  • @JorenHeit 已修复,感谢您的反馈,看来我打错了。
  • @JorenHeit 感谢您的建议。我也在考虑如何重新组织代码。大部分代码参考了一些游戏模式编程博客,但是sn-ps对我来说操作难度比较大。我比较专注于传感器和运动控制,会先尝试了解你的cmets
  • @tianb03 如果您需要更多解释,请给我发电子邮件 (anders43@gmail.com) 干杯
【解决方案3】:

如果您使用的是 g++,那么 valgrind is your friend。 OSX、iOS、Windows、Android、Solaris……也有类似的工具。

有些是商业的,有些是免费的。四处打听。

这些在任何 C/C++ 程序员工具箱中都是必不可少的,它们会告诉您问题所在以及问题所在。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-16
    • 2010-09-24
    • 1970-01-01
    • 2011-06-26
    • 2011-10-07
    • 2011-01-29
    • 2011-05-08
    • 1970-01-01
    相关资源
    最近更新 更多