如果这是一个非常愚蠢的问题,我提前道歉…
目前我有一个循环链表。节点的数量通常保持不变。当我想要添加时,我将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'错误),该列表就可以工作。直观地说,我认为这是因为释放它并没有释放单个节点,而通过正常方式循环是试图多次释放它(加上释放整个块可能会破坏来自仍然存在的节点的所有其他指针?),但是:
- 谁能给我解释一下到底是怎么回事?
- 是否有一种方法来分配节点块,而不是打破东西?
这样做的目的是因为我要调用malloc几十万次,如果事情能快一点就好了。如果有更好的方法来解决这个问题,或者我不能指望它变得更快,我也会很感激听到这一点。:)
谁能给我解释一下发生了什么事?
正是你说的。您正在为所有块分配单个连续内存空间。然后,如果你释放它,所有的内存将被释放。
是否有一种方法来分配节点块,而不是打破东西?
为每个块分配不同的内存段。在你的代码中(这是不完整的)应该是这样的:
for ( i = 0; i < size_block ; i++ ) {
free_nodes[i] = malloc (sizeof( NODE ));
}
首先,你在块中分配节点的方式,你总是必须用从malloc
获得的完全相同的起始地址来free
整个块。这是没有办法的,malloc
是这样设计的。
malloc
/free
之后有相当有效的垃圾收集(针对其缓冲区,而不是针对用户分配),并且您很难实现更好的东西,更好的意思是更有效,但仍然保证数据的一致性。
在你迷失在这样一个项目之前,衡量一下你的程序的真正瓶颈在哪里。如果分配部分有问题,还有另一种更可能是原因的可能性,即设计不良。如果您在链表中使用如此多的元素,以至于分配占主导地位,那么链表可能不是合适的数据结构。考虑使用带有移动光标的数组或类似的东西。
当您释放一个节点时,您释放了分配给该节点的整个分配。您必须安排一次释放整个节点组。
最好的办法可能是保留一个"空闲"节点列表并重用它们,而不是分配/释放每个节点。通过一些努力,您可以安排将节点保持在块中,并首先从"最常用"的块中分配,这样如果整个块为空,您可以释放它。