没有使用delete操作符的shared_ptr内存泄漏问题

3

我已经实现了一个简单的结构体:

struct ListenerNode
{
    ListenerNode() : previous(nullptr), next(nullptr), listener(nullptr), once(false) {}
    std::shared_ptr<ListenerNode> previous;
    std::shared_ptr<ListenerNode> next;
    std::function<void(int)> listener;
    bool once;
};

这将代表一个场景图实现中的实体。我观察到的奇怪行为是,当我简单地使用结构体时:

int main(int argc, char** argv)
{
    ListenerNode n;
}

它存在内存泄漏问题,但当我按照以下方式使用它时:
int main(int argc, char** argv)
{
    ListenerNode* n = new ListenerNode();
    delete n;
}

它不会泄漏内存!我不明白这里发生了什么。我一直认为在没有使用new的情况下创建类/结构体的实例时,当变量超出范围时会立即调用析构函数。

有人能解释一下这里发生了什么吗?我没有看到任何明显的引用计数增加。


2
你如何知道它正在泄漏? - Bryan Chen
2
你在哪里调用 _CrtDumpMemoryLeaks() 函数? - R Sahu
2
如果你在 ListenerNode n; 周围加上额外的一对大括号会怎么样? - timrau
3
此时 n 尚未被销毁。 - timrau
添加一个作用域,你会看到不同之处int main(int argc, char** argv) { { ListenerNode n; } } - billz
显示剩余5条评论
2个回答

7
根据您的评论,您进行了内存泄漏测试,如下代码段所示:
int main(int argc, char** argv) 
{
    ListenerNode n;
    _CrtDumpMemoryLeaks();
}

在这种情况下,在调用_CrtDumpMemoryLeaks()时,n还没有超出作用域。在_CrtDumpMemoryLeaks()之后,您可以毫无问题地访问n的内容。n将在main()的结尾括号处被销毁。
如果您添加了额外的一对括号:
int main(int argc, char** argv) 
{
    { ListenerNode n; }
    _CrtDumpMemoryLeaks();
}

然后,当遇到额外的闭合括号时,n就被销毁了。在调用_CrtDumpMemoryLeaks()时,由于n已经超出作用域,因此无法访问。


0

如果你使用类创建一个列表,那么你将会泄漏内存。不要使用shared_ptr创建循环(如next/previous),它们将无法删除任何内容。

你不需要使用nullptr初始化shared_ptr。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接