【问题标题】:Safe to delete parent of vector of pointers when those pointers have been shared?共享指针时删除指针向量的父级是否安全?
【发布时间】:2020-03-15 03:19:11
【问题描述】:

我正在尝试修复的一个应用程序中出现内存泄漏问题。我怀疑的问题之一是我使用 BNFC 将文件中的行解析为命令:

void LineStreamScriptProvider::populateQueue()
{
    if(shouldPopulate())
    {
        TasScript::ShowAbsyn shower;
        std::string line;
        while(queueSize() < 30 && !stream.eof())
        {
            std::getline(stream, line);
            const char* lineCStr = line.c_str();
            TasScript::Program* lineCmds = TasScript::pProgram(lineCStr);
            TasScript::P* asLeaf = static_cast<TasScript::P*>(lineCmds);
            TasScript::ListCommand* cList = asLeaf->listcommand_;
            for_each(cList->begin(), cList->end(), [this, shower](TasScript::Command* cmd) {
                // log_to_sd_out("Parsed command %s\n", shower->show(cmd));
                std::shared_ptr<TasScript::Command> cmdShared(cmd);
                pushToQueue(cmdShared);
            });
        }
        if(stream.eof())
        {
            afterEOF();
        }
    }
}

供参考:

class P : public Program
{
public:
  ListCommand *listcommand_;
// ...
class ListCommand : public Visitable, public std::vector<Command*>
{
// ...

BNFC 使用new 构造这些,然后返回指针。在不删除cmdShared 持有的值的情况下,delete lineCmds 是否安全?

【问题讨论】:

  • 与其从原始指针创建共享指针,不如一开始就创建共享指针?这就是智能指针的全部内容:管理对象的生命周期。此外,您还可以通过智能指针获得异常安全性,即如果在创建对象时引发异常,它们会为您删除内存。
  • > BNFC 使用new 构造这些

标签: c++ shared-ptr bnfc


【解决方案1】:

抱歉,我不知道 BNFC,它会为您创建原始指针。

不删除 lineCmds 持有的值是否安全 cmdShared?

如果您从原始指针创建共享指针,则共享指针将拥有该资源的所有权。共享指针将保持对该资源的引用计数,直到它降至零,即当该资源的所有共享指针超出范围时,它将尝试销毁该资源。

在这里,您正在创建一个共享指针并将其传递给队列:

std::shared_ptr<TasScript::Command> cmdShared(cmd);
pushToQueue(cmdShared);

共享指针将为您处理内存管理。所以不需要在命令向量上显式调用delete。一旦std::shared_ptr&lt;TasScript::Command&gt; 类型的所有共享指针被销毁,资源也会被销毁。

所以不,在这种情况下删除指针向量是不安全的。


另一个更简单的解决方案是复制TasScript::Command

TasScript::Command cmdCopy(*cmd);

然后将pushToQueue() 更改为const TasScript::Command&amp; 接受,而不是共享指针。然后你不必担心指针被销毁,因为你有一个值的副本。

看起来在您的 while 循环中您正在泄漏内存。 lineCmdscList不用删吗?

【讨论】:

  • 这样吗? mystb.in/evegezufor.cpp pushToQueue 需要使用 shared_ptr,因为它以奇怪的方式跨线程访问。
  • 或者像mystb.in/qakizetaka.cpp 这样更正确?
  • @Soren ListCommand 是您创建的类吗?如果是这样,你不能把它改成class ListCommand : public Visitable, public std::vector&lt;std::shared_ptr&lt;Command&gt;&gt;吗?然后您可以处理共享指针的向量。这将是一个更好的设计,并且更容易在代码中使用。那么就不需要在for_each中创建共享指针了。
  • @Soren 也许您毕竟可以复制该命令。这样您就可以销毁指针,而不必担心循环后任何无效的指针。请参阅我的第二个解决方案。
猜你喜欢
  • 1970-01-01
  • 2010-10-30
  • 1970-01-01
  • 2013-04-14
  • 2015-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多