如果这是一个令人难以置信的愚蠢问题,我会事先道歉......
目前我有一个循环链表。节点数通常保持不变。当我想添加它时,我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:双重免费或损坏'错误),该列表就可以正常工作。直觉上,我认为这是因为释放它不会释放单个节点,并且循环通过正常方式试图多次释放它(加上释放整个块可能会搞砸所有其他指针仍然存在的节点? ),但是:
这样做的目的是因为我正在调用malloc数十万次,如果事情变得更快就会很好。如果有更好的解决方法,或者我不能指望它变得更快,我也希望听到这一点。 :)
答案 0 :(得分:3)
有人可以明确地向我解释发生了什么吗?
正是你所说的。您正在为所有块分配单个连续内存空间。然后,如果你释放它,所有内存都将被释放。
有没有办法按块分配节点而不破坏东西?
为每个块分配不同的内存段。在你的代码中(不完整)应该是这样的:
for ( i = 0; i < size_block ; i++ ) {
free_nodes[i] = malloc (sizeof( NODE ));
}
答案 1 :(得分:1)
释放节点时,可以释放分配节点的整个分配。你必须以某种方式安排立即释放整个节点组。
可能你最好的办法是保留一个“免费”节点列表并重用这些节点而不是分配/释放每个节点。通过一些努力,您可以安排将节点保留在块中并首先从“最常用”块进行分配,这样如果整个块变空,您可以释放它。
答案 2 :(得分:1)
首先,您在块中分配节点的方式,总是必须free
整个块具有与malloc
完全相同的起始地址。没有办法解决这个问题,malloc
就是这样设计的。
自己解决这个问题很复杂,通常不值得。现代运行时在malloc
/ free
后面有非常有效的垃圾收集(对于它的缓冲区,而不是用户分配),你很难获得更好的东西,更好的意思是更有效但仍然保证数据的一致性。
在这样一个项目中失去自己之前,你的程序真正的瓶颈是什么。如果分配部分是一个问题,还有另一种可能性更可能是原因,即糟糕的设计。如果您在链表中使用了这么多元素,以至于分配占主导地位,那么链表可能不是合适的数据结构。考虑使用带有移动光标的数组或类似的东西。