c语言 - 从循环链表中释放错误定位的内存



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

目前我有一个循环链表。节点的数量通常保持不变。当我想要添加时,我将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 detected: double free or corruption'错误),该列表就可以工作。直观地说,我认为这是因为释放它并没有释放单个节点,而通过正常方式循环是试图多次释放它(加上释放整个块可能会破坏来自仍然存在的节点的所有其他指针?),但是:

    谁能给我解释一下到底是怎么回事?
  1. 是否有一种方法来分配节点块,而不是打破东西?

这样做的目的是因为我要调用malloc几十万次,如果事情能快一点就好了。如果有更好的方法来解决这个问题,或者我不能指望它变得更快,我也会很感激听到这一点。:)

谁能给我解释一下发生了什么事?

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

是否有一种方法来分配节点块,而不是打破东西?

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

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

首先,你在块中分配节点的方式,你总是必须用从malloc获得的完全相同的起始地址来free整个块。这是没有办法的,malloc是这样设计的。

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

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

当您释放一个节点时,您释放了分配给该节点的整个分配。您必须安排一次释放整个节点组。

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

相关内容

  • 没有找到相关文章

最新更新