【问题标题】:Is this geeksforgeeks trie implementation having a memory leak problem?这个 geeksforgeeks trie 实现是否存在内存泄漏问题?
【发布时间】:2020-11-01 02:32:19
【问题描述】:

我在读一个geeksforgeeks_implementation_of_trie,发现new创建的TrieNode对象未被删除,在main函数中有一个未被删除的指针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; 
} 

【问题讨论】:

  • 如果这返回一个std::unique_ptr 而不是一个原始指针,那就没有问题了......
  • 那个“极客”网站的代码很差。很少,如果有没有错误的实际代码示例。所以是的,它会泄漏内存。
  • struct TrieNode* 应该表明编写代码的人不知道c++ 或者是通过使用c 实现c++ 来偷懒

标签: c++ memory-management memory-leaks trie


【解决方案1】:

这个函数意味着一个合约,其中函数的调用者负责删除分配的TrieNode。如果调用者不遵守此合同,则只有内存泄漏。

既然你说这个TrieNodemain的任何地方都没有被删除,那么很可能有泄漏。除非你能找到这个结构被删除的地方,否则就会有泄漏。这就是为什么 RAII 是一个如此强大的概念。如果有一个Trie对象包含了所有的TrieNodes并且负责节点的分配和删除,那么你就完全不用担心泄露了。

让调用者负责管理分配的资源是危险的。不要这样做。

如果程序足够简单以至于它所做的只是获取TrieNodes,对它们进行处理,然后退出,您可以争辩说这个特定的实现不一定是泄漏。在这种情况下,内存将在程序退出时释放给操作系统。但这是一个语义论点,提供执行此操作的示例代码是不好的做法,并且可能导致货物狂热的程序员做这种不好的做法。

【讨论】:

    【解决方案2】:

    漏还是不漏...

    根据Wikipedia,泄漏发生在计算机程序错误地管理内存分配时,不再需要的内存不会被释放

    • getNode()的作用是返回一个指向已初始化TrieNode的指针。所以它本身不会泄漏任何东西:我们可以假设,根据它的用途,当函数返回它的指针时,仍然需要对应的对象。

    • 调用上下文确实泄漏了内存:正如您正确指出的那样,它使用getNode() 创建一个节点,并且永远不会删除该节点。这是不好的做法。

    但是你必须在它的上下文中替换这段代码:这篇文章是一个教程。它建议删除为additional exercise

    为什么他们没有在教程中显示删除

    因为如果您必须小心,删除TrieNode 并不是一件容易的事:删除节点还需要找到所有应该删除的引用节点。由于 trie 是一个图,因此可以有多个节点指向同一个目的地。因此,如果您不想因为悬空指针和双重删除而冒着 UB 的风险,就不能盲目地删除这些节点。您需要实现标记算法或某种引用计数

    但不要遵循本教程

    TrieNode 的实现非常糟糕:在现代 C++ 中:

    • 您可以让构造函数初始化 TrieNode,无论它是动态创建的节点还是本地节点。
    • 您将使用智能指针而不是原始指针。由于一个节点本质上可以多次引用,因此您会选择shared_ptr
    • 您可能更喜欢使用vector&lt;shared_ptr&lt;TrieNode&gt;&gt; 甚至map&lt;char, shared_ptr&lt;TrieNode&gt;&gt; 而不是旧式数组。

    但我还是让你把删除作为练习 ;-)

    【讨论】:

      猜你喜欢
      • 2016-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-16
      • 2011-05-16
      相关资源
      最近更新 更多