现代虚拟机如何处理内存分配?

17

我正在编写一个简单的堆栈机器程序,使用C语言编写,主要是为了学习目的。在使用malloc/free进行内存操作后,我认为阅读一些现代虚拟机中的内存分配特定代码是一个好主意。

我下载了Lua源代码并开始阅读它。过了一会儿,我意识到有很多宏定义涉及其中,并且我找不到真正执行内存分配(即malloc调用)的代码。

find . -exec grep -i "malloc" '{}' \; -print

它只打印了一些Lua宏,这些宏中包含“malloc”单词。 Lua虚拟机(和编程语言)根本不使用malloc

所以这引出了一个问题:现代虚拟机如何处理内存分配? Lua如何从堆中分配内存? 除malloc之外还有其他的分配方式吗? 其他方法的优缺点是什么?

我还想知道安全地处理已分配内存的最佳实践、设计模式等方面的信息。 我在Lua源码中看到,在分配内存之前有很多间接操作。 我应该在哪里学习这些内容?


你对哪种虚拟机感兴趣?有一些虚拟机可以虚拟整个计算机,你知道吗?你也在问这些吗? - Alexey Frunze
@AlexeyFrunze,不是的,我只是对用于编程语言的虚拟机感兴趣。 - sinan
好的,标题看起来有点混乱。 - Alexey Frunze
这是那种真的应该迁移到 programmers.se 的罕见问题吗? - finnw
@finnw 问题被错误地迁移到 programmers.se 上,这是常见的吗? - snogglethorpe
@snogglethorpe,以前是这样的(但最近他们让它变得更加困难了)。 - finnw
2个回答

16
Lua绝对使用malloc,以realloc的形式(也可以传递自定义分配器)。然而,由于Lua使用类似99%基于VM的语言的GC,它使用宏自动将GC标头块添加到分配中。
您可以在lmem.clmem.h中找到Lua内存的处理方式,这些都使用VM的全局状态来存储分配器,最初设置为l_alloc(来自lauxlib.c),但可以通过lua_setallocf更改。
最近,LuaJIT添加了分配sinking和计划一些真正酷炫的内存功能,您可以在LuaJIT Garbage Collection文章中阅读。该文章涵盖了许多与VM / JIT内存分配、sinking、聚合和垃圾收集相关的策略和设计。
从各种内存分配器的优缺点来看,使用标准的malloc很简单,但代价是速度慢以及对齐方式和各种额外块的浪费。转向更高级的arena、pool、slab和block分配器,我们可以显著加快速度(特别是对于固定大小的内部VM分配),并避免可能发生的更一般的分配器(例如malloc)会出现的碎片和开销。但当然,这些分配器更复杂,如果您从头开始启动(在像VM这样的更大系统中),则必须对其进行调试,这只是寻求问题的途径,而不是经过试验验证的CRT malloc实现。

谢谢,你能告诉我在哪里使用了 malloc 吗?因为就像我之前说的,我找不到它。我打算跟踪使用 malloc 的代码以更好地理解内部情况。 - sinan
@sinan:让我快速找到它。 - Necrolis
谢谢,但是realloc不是需要一个malloccalloc的调用吗?所以应该有一些malloccalloc的调用... - sinan
是的,但LUA源代码不包含realloc源代码,因为realloc是一个标准函数,它是C运行时的一部分。如果想查看realloc源代码,您需要下载glibc的源代码,如果我没记错的话。 - sashoalm
8
不,你可以使用realloc(3)而不必使用malloc(3)。来自手册页的说明:如果ptr为NULL,则realloc()与调用malloc()相同,分配size字节的内存空间。 - Mackie Messer

5
Lua核心不使用malloc及其相关函数。它依赖于用户提供的内存分配函数,该函数具有类似于realloc的语义(但在处理NULL指针和大小为0时更精确)。请参见lua_Alloc
辅助Lua库提供了一个方便的luaL_newstate函数,该函数通过核心的lua_newstate函数创建一个Lua状态,并使用基于标准reallocfree的内存分配函数。其他客户端可以使用适合他们应用程序的任何内存分配方式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接