如何在 PIC 中使用malloc()
和功能?free()
我检查了stdlib.h
标题,没有提到它们。我正在使用 MCC18。
有人不得不使用它们吗?
我需要它们,因为我正在将一个库从 Windows XP 移植到 PIC。移植指南说
使操作系统的特定功能适应我的 PIC 功能
但我不知道如何“翻译” malloc()
andfree()
函数。
如何在 PIC 中使用malloc()
和功能?free()
我检查了stdlib.h
标题,没有提到它们。我正在使用 MCC18。
有人不得不使用它们吗?
我需要它们,因为我正在将一个库从 Windows XP 移植到 PIC。移植指南说
使操作系统的特定功能适应我的 PIC 功能
但我不知道如何“翻译” malloc()
andfree()
函数。
malloc()
在微控制器中通常被认为是“坏事”。但是,如果您绝对需要它,那么您将需要找到第三方版本。
如果幸运的话,您移植的代码可能不依赖于重用内存块。如果是这种情况,您可以编写一个简单的分配器,它将指针返回到 RAM 缓冲区,然后将指针前进请求的块大小。
在将 PC 库移植到微控制器之前,我已经成功地使用过这种方法。
下面,您将使用 设置分配器my_malloc_init()
并使用 分配内存my_malloc()
。my_free()
是否可以满足依赖但实际上不会做任何事情。当然,最终你会用完空间。
为了使这项工作发挥作用,您需要测量代码的最坏情况下的内存需求(如果可能,请在 PC 上执行此操作),然后进行HEAP_SIZE
相应设置。在进入需要动态内存的库部分之前,调用my_malloc_init()
. 在重新使用之前,确保没有任何东西仍然指向heap
。
uint8_t heap[HEAP_SIZE];
uint8_t *heap_ptr;
void my_malloc_init(void)
{
heap_ptr = heap;
}
void *my_malloc(size_t len)
{
uint8_t *p = heap_ptr;
heap_ptr += len;
if (heap_ptr >= heap + HEAP_SIZE)
return NULL;
else
return p;
}
void my_free(void)
{
// do nothing
}
(注意:在现实世界中,您可能需要考虑指针对齐,即向上舍入heap_ptr
2 或 4 个字节)
另一种选择是使用比malloc()
通常提供的更简单的分配结构,例如FreeList,尽管这可能不允许您分配可变大小的块。
这很难回答您的问题,但是动态内存分配通常不适合小型 RAM 环境并且在没有操作系统的情况下(例如在微控制器世界中)......您在嵌入式环境中可用的堆空间通常是以数百字节为单位...
实现 malloc 和 free 本质上是维护“空闲段”结构的链表,正如您可以想象的那样,与通常可用的内存量相比,与空闲段相关的元数据并不是微不足道的......这就是“开销" 管理动态内存池会消耗大量可用资源。
我不知道 C18 标准库是否支持malloc
and free
,但Microchip 应用笔记 AN914展示了如何实现自己的。
在任何情况下,Thomas 和其他发帖者都建议,在 PIC 上使用具有非常小的 RAM 空间的动态内存是充满危险的。由于缺乏完整的操作系统为您提供的更高级的虚拟内存管理器,您可能会迅速耗尽连续空间,从而导致分配失败和崩溃。更糟糕的是,它可能不是确定性的,调试起来可能会很痛苦。
如果您正在做的事情是在运行时真正动态确定的(对于大多数嵌入式事物来说很少见),并且您只需要在几个非常特殊的场合分配空间,我可以看到malloc
并且free
可以接受。
在许多应用程序中,需要分配内存,但不需要释放任何东西,同时保留在它之后分配的东西。在这样的系统上,只需使用链接器使用所有可用 RAM 定义一个数组,设置一个指向该数组开头的指针,然后使用一个简单易用的 malloc 函数:
字符 *next_alloc; 无效 *malloc(int 大小) { 字符 *this_alloc; this_alloc = next_alloc; if ((END_OF_ALLOC_SPACE - this_alloc) < 大小) 返回-1; next_alloc += 大小; 返回 this_alloc; } 无效免费(无效*ptr) { 如果(指针) next_alloc = (char*)ptr; }
很好也很简单,对于任意数量的分配,总开销只有两个字节。在块上调用 free() 将释放该块及其之后的所有内容。
稍微复杂的分配模式可以通过使用两个指针来处理——一个从内存底部向上分配内容,一个从内存顶部向下分配。如果堆中的数据是同质的并且知道所有外部引用在哪里,也可以使用压缩垃圾收集器。