【问题标题】:Freeing malloc'ed memory from circular linked list从循环链表中释放 malloc 的内存
【发布时间】:2011-09-24 01:49:59
【问题描述】:

如果这是一个非常愚蠢的问题,我提前道歉......

目前我有一个循环链表。节点的数量通常保持不变。当我想添加时,我会 malloc 一些节点(例如 100000 左右)并将其拼接起来。当我一个一个地 malloc 节点时,这部分工作正常。

我想尝试按块分配:

NODE *temp_node = node->next;
NODE *free_nodes = malloc( size_block * sizeof( NODE ) );
node->next = free_nodes;
for ( i = 0; i < size_block - 1; i++ ) {
    free_nodes[i].src = 1;
    free_nodes[i].dst = 0;
    free_nodes[i].next = &free_nodes[i+1];
}
free_nodes[size_block - 1].next = temp_node;

只要我不尝试释放任何东西(“检测到 glibc:双重释放或损坏”错误),该列表就可以工作。直观地说,我认为这是因为释放它不会释放单个节点,并且通过正常方式循环尝试多次释放它(加上释放整个块可能会破坏仍然存在的节点的所有其他指针? ),但是:

  1. 谁能明确地向我解释发生了什么?
  2. 有没有办法按块分配节点而不破坏东西?

这样做的目的是因为我调用 malloc 数十万次,如果事情更快,那就太好了。如果有更好的解决方法,或者我不能指望它会变得更快,我也会很高兴听到这个消息。 :)

【问题讨论】:

    标签: c linked-list


    【解决方案1】:

    有人可以明确地向我解释发生了什么吗?

    正是你所说的。您正在为所有块分配一个连续内存空间。然后如果你释放它,所有的内存都会被释放。

    有没有办法按块分配节点而不破坏东西?

    为每个块分配不同的内存段。在您的代码中(不完整)应该是这样的:

    for ( i = 0; i < size_block ; i++ ) {
        free_nodes[i] = malloc (sizeof( NODE ));
    }
    

    【讨论】:

      【解决方案2】:

      首先,您以块为单位分配节点的方式,您始终必须使用与从malloc 获得的起始地址完全相同的整个块free。没办法,malloc就是这样设计的。

      自行解决这个问题很复杂,而且通常不值得。现代运行时在malloc/free 后面有非常有效的垃圾收集(对于它的缓冲区,而不是用于用户分配),你很难实现更好的东西,更好的意思是更有效但仍然保证你的一致性数据。

      在这样一个项目中迷失自己之前,先衡量一下程序的真正瓶颈所在。如果分配部分有问题,则还有另一种可能性更大,即设计不良。如果您在链表中使用了如此多的元素,以至于分配占主导地位,那么链表可能不是合适的数据结构。考虑使用带有移动光标的数组或类似的东西。

      【讨论】:

      • 接受,因为我最终重新安排了事情的运作方式,并在坐下来思考重要的事情后回到了循环缓冲区。感谢所有回答的人! :)
      • @user962158,谢谢。对于投反对票的人,如果他们碰巧再次经过这里,您介意解释一下吗?
      • @JensGustedt - 这是一个彻底的死灵,但我相信我知道你为什么被否决:C 没有垃圾收集。
      • @Polynomial,啊,我从来没有说过 C 有垃圾收集。我说过 malloc/free 的实现在幕后有它自己。
      • @JensGustedt - 这可能是让你被否决的误解。虽然 malloc 和 free 只是倾向于调用底层操作系统调用来进行内存管理(例如 VirtualAlloc/VirtualFree),所以这几乎是一个有争议的问题。
      【解决方案3】:

      当你释放一个节点时,你释放了该节点被分配的整个分配。您必须以某种方式安排一次释放整个节点组。

      您最好的选择可能是保留“空闲”节点列表并重复使用这些节点,而不是分配/释放每个节点。通过一些努力,您可以安排将节点保留在块中并首先从“最常用”的块分配,这样如果整个块变空,您可以释放它。

      【讨论】:

        猜你喜欢
        • 2020-12-08
        • 2012-10-31
        • 2021-08-11
        • 1970-01-01
        • 2021-04-28
        • 1970-01-01
        • 2010-10-30
        • 2015-09-10
        相关资源
        最近更新 更多