C 固定大小类型的动态分配

C 固定大小类型的动态分配,c,linux,memory,memory-management,malloc,C,Linux,Memory,Memory Management,Malloc,假设我们有一些固定长度的数据类型,例如C结构: struct T { ...; } 分配T的一种方法是: T* create_t() { return (T*) malloc(sizeof(T)); } 和取消分配: void destroy_t(T* t) { free(t); } malloc使用内存分配算法,以不同的方式处理不同大小的块 假设我们正在编写一个经常调用create_t和destroy_t的程序,并且一次(以伪随机顺序)分配了很多t项 考虑到所需的内存是固定大小的

假设我们有一些固定长度的数据类型,例如C结构:

struct T
{
    ...;
}
分配T的一种方法是:

T* create_t() { return (T*) malloc(sizeof(T)); }
和取消分配:

void destroy_t(T* t) { free(t); }
malloc使用内存分配算法,以不同的方式处理不同大小的块

假设我们正在编写一个经常调用create_t和destroy_t的程序,并且一次(以伪随机顺序)分配了很多t项

考虑到所需的内存是固定大小的元素,是否有可能编写一个优于malloc的通用实现的自定义内存分配方案

例如,我们可以预先分配一个包含大小为T的元素的巨大数组,然后使用这些元素,但是跟踪哪些元素已分配,哪些元素未分配的最好方法是什么

当使用相同大小的大量分配调用时,Linux上的malloc最终使用什么算法


与一般的malloc相比,这个定制方法的性能大致如何?

据我所知,使用的内存管理是一种“bucket”管理

malloc
将空闲内存段保存在bucket中,调用时,尝试将其中一个最合适的块传递给调用方

不过,只要下载libc的源代码,自己动手就行了


编写内存管理是相当棘手的,目前使用的算法已经投入了大量的精力。我确实相信(尤其是作为一个人)很难想出比那些家伙更好的东西。

Q:考虑到所需的内存是固定大小的元素,是否有可能编写一个优于malloc的通用实现的自定义内存分配方案

A:也许吧。这可能是一项不平凡的事业

任何给定的操作系统都可能有不同的“malloc()”实现。Linux的标准(例如)是GNULIBC。您可以在此处找到来源:


“希望有帮助

首先,您可以有几个
malloc
的实现。例如,Glibc-malloc(解释)是,但malloc是。而且各种各样的食物是众所周知的

还请注意,一个简单的实现

void *malloc (size_t sz)
{
   errno = ENNOMEM;
   return 0;
}
可能与的字母一致,但不符合其精神(例如在Posix和C99中)

实际上,
malloc
是通过像and
munmap(2)
这样询问一些内存块来实现的,有时这些内存块都与and相关。由于
的结果,malloc
在程序的一次运行到下一次运行时可能会有所不同
malloc
能够处理许多相同大小的分配,但最终可能会导致运行时间很长的程序出现错误

您也可以使用例如中的切片分配器,但它可能很少有用。您也可以使用(例如,使用
GC_malloc
而不是
malloc
,而不必显式地使用
free

实际上,在Linux上,
malloc
工作得相当好。我认为你不应该为此烦恼。当然,它的设计目的是最小化内存分配低级操作,如
mmap
(这很昂贵;一个好的
malloc
实现可以很好地管理内存池,并在从内核请求之前尝试重新使用
空闲的
-d内存)。还存在与多线程等相关的问题

在为降低应用程序中
malloc
的成本而烦恼之前,您应该对其进行测量(这对于调试
malloc
相关bug也是有用的)。在应用程序中,
malloc
的成本通常并不重要。如果你真的愿意,你可以自己管理,但我不确定你是否应该麻烦。(优化前先测量)。在今天的机器上,缓存考虑因素对代码的实际性能也起着主导作用。

至于#1-其他人已经处理了这一点,简言之,glibc做得相当好,其他malloc在各种情况下可能做得更好

然而,关于你的第二个问题:定制的如何执行

•通常情况下,一个手动编码的、低级别的、了解应用程序自身使用模式和需求的自由列表分配器的实现可能会比GNU libc提供的一般情况算法表现更好

•但你必须通过写作证明这一点

顺便说一句,这里有一些相关的答案


您还可以查看各种文件系统驱动程序中磁盘扇区使用情况的表示,因为它们有效地解决了同样的问题——固定大小的块/扇区在各种负载下以伪随机间隔分配——而大多数malloc将专注于通用性。

听起来好像你即将想出一个解决方案。使用空内存块的空间来保存指向下一个可用内存块的指针。通过这种方式,可以创建可用内存块的就地链接列表。这里还有更高级的方案。在Windows上是的(除了新的并发CRT),在其他任何系统上可能都不是。这与内核无关,都在libc中。