我正在编写一个简单的任务调度程序,并在具有4kB RAM的德州仪器cc430F5137上使用动态内存分配。我同意这不是一个好习惯,但暂时让我们假设使用动态内存分配是我的应用程序要求。
在我的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()
在这方面的表现如何。
假设我的记忆空间,
第一个任务已注册,因此m_info[0]
的前8个字节和m_index[0]
的后6个字节。
现在,当我的第二个任务调用此函数时,会发生什么?我猜测的是,对于m_info,它将首先查找16个字节的连续数据,并且只会在前14个字节之后找到它,它将更改m_info[0]
的地址并复制内容然后添加{{1 }}。当调用m_info[1]
时,它只会在此(14 + 16)字节后找到12个字节,并在此处放置m_index
和m_index[0]
。
请看一下图片 [IMG] http://i.imgur.com/iJnOG2T.jpg[/img]
我如何利用之前的空间?
我需要m_index[1]
结构来实现某种搜索算法,所以它也是必要的
答案 0 :(得分:2)
如果这是真的那么我之前的所有空间都被浪费了?
没有;如果realloc()
移动而不是扩展分配,则先前的分配将被释放回堆中,并可供后续分配使用。
你无疑会做的是导致块的碎片化,增加分配失败的变化,并且经历广泛不同的分配时间。
如果必须使用realloc()
,则应该使用一种算法,通过一次分配多个块来降低块移动的频率。例如,当需要初始分配时,而不是分配一个块分配16;后续任务可以使用16个预分配块中的一个(确定性地)。当这些用尽时,再分配16个而不是一个。或者,您可以使用几何级数,例如从4个块开始,然后从8,16,32开始,或许达到某个最大值,以便此后增量固定为32.这将减少碎片以及必须分配和移动数据的变化。
答案 1 :(得分:0)
经过大量的不使用动态内存的评论和答案后,我仍然找到了解决问题的方法。
我在我的代码中更改了这个
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;
通过这个,我的realloc()为m_combined分配了连续的内存,我的碎片问题得到了解决。 (我猜是因为在逐步分析记忆后)。