首页 文章

链接列表包含其他链接列表和免费

提问于
浏览
8

我有一个通用的链表实现,其中包含一个包含void * to data的节点struct和一个包含对head的引用的list结构 . 现在这是我的问题,链表中的节点可以通过其void *保存对另一个链表的引用 . 当我释放包含较小列表的较大列表时,这会导致内存泄漏 . 所以我想知道有没有办法检查void *是否指向另一个列表,所以我跟随并释放它也只是数据 .

如果我在我的struct的开头添加一个关键字,我可以通过解除引用void *来检查并找出它是一个列表?

编辑:调用者不插入我的函数插入的较小列表我不希望调用者处理重定位多个列表只是他们持有指针的列表 .

4 回答

  • 1

    这个问题实际上取决于清理列表中的条目的责任 . 如果你的结构负责清理 void * 字段引用的内存,那么你手头有一个更大的问题,即给定 void * 引用一些任意内存块你永远不知道解除分配它的正确方法是什么 . 例如,如果你在C std::vector 的行中有一个动态数组的实现,那么 void * 可能指向一个本身包含指针的结构,你的列表需要知道它必须下降到该结构中递归释放其动态分配的块 . 你're describing, where you'泄漏嵌套列表的情况 - 只是这个更普遍问题的一个特例 .

    另一方面,如果列表不负责清理它存储的 void * 引用的内存,那么你根本不应该担心这个问题 .

    如果您的列表确实具有所有权语义并且需要清理存储在其中的元素的内存,我强烈建议您不要使用幻数来确定您是否有嵌套列表 . 相反,您应该让客户端为您提供一个函数指针,其中包含一个释放例程,以便在插入到列表中的元素上运行 . 这样,您的代码可以使用用户提供的清理代码来确保清除列表中存储的所有元素 .

  • 1

    这不仅仅是你的 void* 可以指向一个列表 . 它可以指向任何动态分配的内存 .

    GLib处理这个问题的方式是说它有责任确保释放列表的 void *data 所指向的任何内容 . 见http://library.gnome.org/devel/glib/unstable/glib-Doubly-Linked-Lists.html#g-list-free .

    替代方案(GLib也提供)是创建一个函数,它接受一个函数指针,并在每个 void *data 遍历列表时调用它 . 查找 g_list_free_full .

  • 6

    我的建议是尽可能简化一些事情,并简单地确保一个链表只包含一种类型的对象 .

    如果你不能这样做,我可能会让列表中的每个节点不仅包含一些数据,还包含一个指向知道如何正确释放该类型项的函数的指针 . 不可避免地,在为链表创建特殊代码两周后,您将决定还需要另一个幻数来保存动态数组等 .

  • 0

    要回答“如果我在我的结构的开头添加一个关键字,我可以通过取消引用void *并找出它是一个列表?”的智慧数字的问题 .

    是的,你可以做到这一点,但很少有人会推荐它 . 只是要确定不会发生'magic'值 . 这是一个非常大的问题 . 您想要考虑您可能指向的其他内容以及在表示为无符号整数时可能需要的值 . 请记住,如果您确定它是一个列表,您将释放它,因此如果您错了,可能会崩溃并烧毁 .

    最简单有效的解决方案是,如果您需要一个Node知道它指向一个列表,请在节点中提供一个标记,表示如此 .

    如果你真的希望列表有责任释放它的所有内容,你需要的不仅仅是一个标志,你需要知道每个免费的方法 . 这可能是一个id或类似指向函数的指针,它释放了它的内容 .

相关问题