我正在阅读和试验本书中的指针,
http://shop.oreilly.com/product/0636920028000.do
在本书的第6章中,在避免malloc/free Overhead标题下,作者建议如何在进行大量结构内存分配/解除分配时避免malloc/free开销.
以下是他编写函数的方式,
#define LIST_SIZE 10
Person *list[LIST_SIZE];
void initializeList()
{
int i=0;
for(i=0; i<LIST_SIZE; i++)
{
list[i] = NULL;
}
}
Person *getPerson()
{
int i=0;
for(i=0; i<LIST_SIZE; i++)
{
if(list[i] != NULL)
{
Person *ptr = list[i];
list[i] = NULL;
return ptr;
}
}
Person *person = (Person*)malloc(sizeof(Person));
return person;
}
void deallocatePerson(Person *person)
{
free(person->firstName);
free(person->lastName);
free(person->title);
}
Person *returnPerson(Person *person)
{
int i=0;
for(i=0; i<LIST_SIZE; i++)
{
if(list[i] == NULL)
{
list[i] = person;
return person;
}
}
deallocatePerson(person);
free(person);
return NULL;
}
Run Code Online (Sandbox Code Playgroud)
我从他的代码中了解到,他创建了一个内存池数组,指向struct person类型,然后用NULL初始化每个数组元素.
接下来,我们将使用getPerson函数从池中获取内存.这个函数检查!= NULL,我认为每次都会失败.所以再次它将是相同的,因为malloc和内存不会随时从池中分配.
接下来,我们将使用getPerson函数从池中获取内存.这个函数,
!=NULL我认为每次都会失败.
只要您继续getPerson重复呼叫,每次检查都会失败.但是,如果混合使用getPerson和returnPerson,某些NULL检查将成功,因为returnPerson将非NULL值放入数组中.
这种观察对于理解该方法至关重要:该阵列用作struct Person已分配malloc但不再使用的块的小型临时存储.malloc如果有可用的代码,您的代码将从此特殊列表中获取可用块,而不是再次调用.
在您进行数千次分配但LIST_SIZE在任何给定时间永远不会保持活动对象的情况下,malloc呼叫次数限制为LIST_SIZE.
这是处理开销的方法吗?
这是使用旁视列表的一种变体,这是一种非常重要的优化技术,Microsoft创建了一个API用于驱动程序代码.一种更简单的方法将Person *list[LIST_SIZE]用作已释放块的堆栈,即使用最后释放块的索引而不使用循环.
另一种方法是设置这些块的链表,重用块本身的内存来存储next指针.但是,对于介绍性的嘘声,这种技术可能过于复杂.