在没有操作系统的情况下分配运行时内存

时间:2019-04-03 03:19:49

标签: c memory memory-management

最近,我一直在考虑如何完成编译时内存分配。据我所知,编译器在编译期间会为变量分配固定数量的字节。对于这样的语句,这很有意义:

char buffer[256];

编译器将为该变量分配256个字节的内存,这将是该变量的结尾。如果要动态创建内存,则需要使用操作系统提供的诸如malloc之类的功能。然后我想到了这个功能,它不会使用任何与操作系统相关的功能,但会像动态分配一样起作用。

*char malloc(size_t size) {
    char (*mem)[size];
    return mem;
}

编译器无法预先分配内存,因为在程序运行时可以多次调用此函数。这将如何工作?编译器将如何处理这样的函数?我以为操作系统可以处理此问题,但这并不使用任何依赖于操作系统的功能,这意味着它可以在没有操作系统的硬件上运行。

2 个答案:

答案 0 :(得分:1)

首先,*char应该是char*,而mem不能是指针::

char* malloc(size_t size) {
    char mem[size];
    return mem;
}

这将size字节的内存分配为堆栈上的局部变量。如您所知,函数退出时局部变量将被销毁。它返回一个指向局部变量的指针,然后由于函数退出,局部变量被销毁。实际上,该空间将被重新用于下一个函数调用的局部变量。

如果您尝试以此方式分配两个内存块,则可能会获得相同的地址:

char *mem1 = malloc(10); // using your malloc
char *mem2 = malloc(10); // using your malloc
// probably mem1 and mem2 point to the same memory now

如果您调用另一个函数,则内存可能会损坏,因为该函数也被允许使用局部变量:

char *mem1 = malloc(10); // using your malloc
strcpy(mem1, "abcde"); // if you're lucky, strcpy won't crash...
printf("Hello world.\n");
printf("mem1 contains %s\n"); // it won't be abcde because strcpy or printf overwrote the memory

简而言之:

  

这将如何工作?

不会。

答案 1 :(得分:-1)

为了缩小OS一词的范围-当您说OS时,实际上是指Windows或Unix之类的“桌面OS”,它不仅处理多任务,而且还处理内存分配,文件系统,驱动程序等。也是RTOS,除了处理多任务外什么都不做-他们不在乎动态内存分配。

不使用“台式机操作系统”的应用程序(例如微控制器应用程序),但是由于某种困惑的原因,无论如何仍要使用malloc,请在链接时为堆预留一定数量的RAM。 malloc然后在该存储区上进行统治,并从那里取其所需的存储。在这种情况下,malloc仅由编译器库实现和处理。

这说明在此类应用程序中使用malloc是毫无意义的。首先,嵌入式系统不会运行多个程序,而且它们永远不会停止执行程序,因此free()内存永远都没有意义-您要为谁释放它?没有其他程序可以共享RAM。您的程序具有对所有可用RAM内存的独占访问权。

因此,您在RAM中将此固定区域标记为堆,并禁止除malloc之外的任何人使用,该区域也可以存储静态分配的变量。这实际上是在浪费空间。因为无论如何,您的程序必须能够处理最坏的RAM峰值使用率峰值。那时,无论是静态存储,堆栈存储还是堆存储,您都必须有一定数量的可用内存。

这意味着任何此类程序都必须提前预留该内存,否则它将损坏-它需要与最坏情况所需的RAM数量完全相同的RAM。而且由于必须支持这种最坏的情况,因此您无法真正以任何明智的方式将该内存用于其他目的。

对于存储临时变量,已经有了堆栈,它更快,更安全。因此,您不需要malloc

这是为什么在没有OS的系统中永远不使用堆分配的主要原因-这没有任何意义。我一直看到困惑的PC程序员开始嵌入式系统编程,并且在您不了解之前,他们开始使用malloc,因为他们“不知道编译时需要多少内存”。但是在嵌入式系统上,您必须始终了解这一点-您需要足够的知识来处理最坏的情况。因此,您需要为所有内容设置固定的最大限制。