Realloc() 即使经过大量阅读也无法理解
Realloc() Unable to understand even after lots of reading
我正在编写一个简单的任务调度程序,并在我的 Texas Instruments cc430F5137 上使用动态内存分配,它有 4kB RAM。我同意这不是一个好的做法,但暂时让我们假设我的应用程序要求使用动态内存分配。
在我的 OS.c 文件中
我有两个结构,
typedef struct
{
task_t task;
uint8_t next;
uint8_t prev;
uint8_t priority;
} info_t;
typedef struct
{
task_t task;
uint8_t index;
} index_t;
info_t
的大小为 8 个字节,index_t
的大小为 6 个字节。
我也是
index_t* m_index;
info_t* m_info;
然后我有初始化函数,我在里面做
m_info = NULL;
m_index = NULL;
现在我有一个函数 registerTask(& task)
,它获取要调度的函数的地址。在这个函数中我做
m_info = (info_t*)realloc(m_info,(num_registered_tasks + 1) * sizeof(info_t));
然后设置.priority,next,task,prev的值
那我就
m_index = (index_t*)realloc(m_index,(num_registered_tasks + 1) * sizeof(index_t));
并设置任务和索引的值。
并做 num_registered_tasks++;
我的问题是 realloc()
在这方面的表现如何。
假设我的记忆space,
第一个任务已注册,因此它将有 m_info[0]
的前 8 个字节和 m_index[0]
的后 6 个字节。
现在当我的第二个任务调用这个函数时,会发生什么?我猜测的是,对于 m_info 它会首先寻找 16 个字节的连续数据,并且只会在前 14 个字节之后找到它,它会更改 m_info[0]
的地址并复制内容然后添加 m_info[1]
。而调用m_index
时,只会在这(14+16)个字节之后找到12个字节,将m_index[0]
和m_index[1]
放在这里。
请看图片
[img]http://i.imgur.com/iJnOG2T.jpg[/img]
我怎样才能同时使用之前的space?
我需要 index_t
结构来实现某种搜索算法,因此也有必要
If this is true then all my previous space is being wasted?
否;如果 realloc()
移动 而不是扩展分配,则先前的分配将释放回堆并可供后续分配使用。
你无疑会做的是导致块碎片化,增加分配失败的变化,并经历大相径庭的分配时间。
如果您必须使用 realloc()
,您可能应该使用一种算法,通过一次分配多个块来减少块移动的频率。例如,当需要初始分配时,而不是分配一个块分配 16;后续任务可以使用 16 个预分配块中的一个(确定性地)。当这些都用完时,再分配 16 个而不是一个。或者,您可以使用几何级数,比如从 4 个块开始,然后可能是 8、16、32 到某个最大值,以便此后增量固定为 32。这将减少碎片以及必须分配和移动数据的变化。
经过很多不使用动态内存的评论和回答,我仍然找到了一种方法,当时正在解决我的问题。
我在我的代码中更改了这个
typedef struct
{
task_t task;
uint8_t next;
uint8_t prev;
uint8_t priority;
} info_t;
typedef struct
{
task_t task;
uint8_t index;
} index_t;
typedef struct
{
info_t m_info;
info_t m_index;
} combined_t;
combined_t* m_combined;
由此,nw my realloc() 将连续内存分配给 m_combined 并且我的碎片问题得到解决。 (嗯,我猜是因为在一步步分析内存之后)。
我正在编写一个简单的任务调度程序,并在我的 Texas Instruments cc430F5137 上使用动态内存分配,它有 4kB RAM。我同意这不是一个好的做法,但暂时让我们假设我的应用程序要求使用动态内存分配。
在我的 OS.c 文件中
我有两个结构,
typedef struct
{
task_t task;
uint8_t next;
uint8_t prev;
uint8_t priority;
} info_t;
typedef struct
{
task_t task;
uint8_t index;
} index_t;
info_t
的大小为 8 个字节,index_t
的大小为 6 个字节。
我也是
index_t* m_index;
info_t* m_info;
然后我有初始化函数,我在里面做
m_info = NULL;
m_index = NULL;
现在我有一个函数 registerTask(& task)
,它获取要调度的函数的地址。在这个函数中我做
m_info = (info_t*)realloc(m_info,(num_registered_tasks + 1) * sizeof(info_t));
然后设置.priority,next,task,prev的值
那我就
m_index = (index_t*)realloc(m_index,(num_registered_tasks + 1) * sizeof(index_t));
并设置任务和索引的值。
并做 num_registered_tasks++;
我的问题是 realloc()
在这方面的表现如何。
假设我的记忆space,
第一个任务已注册,因此它将有 m_info[0]
的前 8 个字节和 m_index[0]
的后 6 个字节。
现在当我的第二个任务调用这个函数时,会发生什么?我猜测的是,对于 m_info 它会首先寻找 16 个字节的连续数据,并且只会在前 14 个字节之后找到它,它会更改 m_info[0]
的地址并复制内容然后添加 m_info[1]
。而调用m_index
时,只会在这(14+16)个字节之后找到12个字节,将m_index[0]
和m_index[1]
放在这里。
请看图片 [img]http://i.imgur.com/iJnOG2T.jpg[/img]
我怎样才能同时使用之前的space?
我需要 index_t
结构来实现某种搜索算法,因此也有必要
If this is true then all my previous space is being wasted?
否;如果 realloc()
移动 而不是扩展分配,则先前的分配将释放回堆并可供后续分配使用。
你无疑会做的是导致块碎片化,增加分配失败的变化,并经历大相径庭的分配时间。
如果您必须使用 realloc()
,您可能应该使用一种算法,通过一次分配多个块来减少块移动的频率。例如,当需要初始分配时,而不是分配一个块分配 16;后续任务可以使用 16 个预分配块中的一个(确定性地)。当这些都用完时,再分配 16 个而不是一个。或者,您可以使用几何级数,比如从 4 个块开始,然后可能是 8、16、32 到某个最大值,以便此后增量固定为 32。这将减少碎片以及必须分配和移动数据的变化。
经过很多不使用动态内存的评论和回答,我仍然找到了一种方法,当时正在解决我的问题。
我在我的代码中更改了这个
typedef struct
{
task_t task;
uint8_t next;
uint8_t prev;
uint8_t priority;
} info_t;
typedef struct
{
task_t task;
uint8_t index;
} index_t;
typedef struct
{
info_t m_info;
info_t m_index;
} combined_t;
combined_t* m_combined;
由此,nw my realloc() 将连续内存分配给 m_combined 并且我的碎片问题得到解决。 (嗯,我猜是因为在一步步分析内存之后)。