这个极客对极客的trie实现是否存在内存泄漏问题
Is this geeksforgeeks trie implementation having a memory leak problem?
我正在阅读一个geeksfoekees_implementation_of_tree,我发现new
创建的TrieNode
对象被取消删除,在主函数中,有一个取消删除的指针root
:
struct TrieNode *root = getNode();
在函数getNode()
中还有未删除的指针pNode
,是否存在内存泄漏?是否应该有一个函数负责销毁由指针组成的trie树?
struct TrieNode *getNode(void)
{
struct TrieNode *pNode = new TrieNode;
pNode->isEndOfWord = false;
for (int i = 0; i < ALPHABET_SIZE; i++)
pNode->children[i] = NULL;
return pNode;
}
此函数表示一个约定,其中函数的调用方负责删除分配的TrieNode
。只有当调用方不遵守此合约时,内存才会泄漏。
由于您说TrieNode
没有在main
中的任何位置删除,因此可能存在泄漏。除非你能找到这个结构被删除的地方,否则就存在漏洞。这就是为什么RAII是一个如此强大的概念。如果有一个包含所有TrieNode
的Trie
对象,并负责节点分配和删除,那么您根本不必担心泄漏。
让调用者负责管理分配的资源是危险的。不要这么做。
如果程序足够简单,它所做的只是获取TrieNode
,用它们做一些事情,然后退出,那么您可以争辩说,这个特定的实现不一定是泄漏。在这种情况下,内存将在程序退出时释放给操作系统。但这是一个语义争论,提供这样做的示例代码是一种糟糕的做法,可能会导致狂热的程序员做出这种糟糕的做法。
泄漏或不泄漏
根据维基百科的说法,当计算机程序错误地管理内存分配,不再需要的内存没有被释放时,就会发生泄漏:
-
getNode()
的作用是返回一个指向初始化的TrieNode
的指针。因此,它本身不会泄漏任何内容:我们可以假设,根据它的用途,当函数返回指针时,仍然需要相应的对象。 -
调用上下文确实会泄漏内存:正如您正确指出的,它创建了一个具有
getNode()
的节点,并且从不删除该节点。这是不好的做法。
但您必须在其上下文中替换此代码:本文是一篇教程。它建议将删除作为一项额外的工作。
为什么它们在教程中不显示删除
因为删除TrieNode
不是一件容易的事,如果你必须自己小心:删除一个节点还需要找到所有应该删除的引用节点。由于trie是一个图,因此多个节点可以指向同一个目的地。因此,如果你不想因为悬挂指针和双重删除而冒UB的风险,你就不能盲目删除这些节点。你需要实现标记算法或某种参考计数
但不要遵循本教程
这个TrieNode
实现非常糟糕:在现代C++中:
- 您可以让构造函数初始化
TrieNode
,无论它是动态创建的节点还是本地节点 - 您应该使用智能指针而不是原始指针。由于一个节点本质上可以被引用多次,因此您应该选择
shared_ptr
- 您可能更喜欢使用CCD_ 19甚至CCD_
但我还是让你把删除作为练习;-(
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 为什么以下C++代码中存在内存泄漏?
- 以下代码是否存在内存泄漏?
- 存在内存访问异常,但我不确定我的代码中出了什么问题
- gpc服务器不会释放内存,是否存在内存泄漏?
- 存在内存泄漏问题的链接列表
- QT图像查看器示例,可能存在内存泄漏
- 为什么堆栈中的函数局部变量之间存在内存空间
- C :当居民记忆缓慢增加时,是否存在内存泄漏
- 是否存在内存泄漏,如果是,为什么?
- 如果函数返回 std::vector<std::string>,是否存在内存泄漏?
- 检测到指针引用可能存在内存泄漏
- 是否可能存在内存泄漏以在堆上分配shared_ptr
- 在这个关于指针的C++代码示例中是否存在内存泄漏
- 是否存在内存泄漏
- 尽管释放了分配的内存,但仍存在内存泄漏
- 复制构造函数中存在内存泄漏
- 优先级队列中可能存在内存泄漏
- C++中非常大的数组存在内存问题
- 如果我将一个POD结构分配给另一个POD组织,是否存在内存泄漏