Forth中的内存管理

J C*_*per 13 heap memory-management forth

所以我只是在学习Forth,并且好奇是否有人可以帮助我理解内存管理通常如何工作.目前我只有(一些)使用C stack-vs-heap范例的经验.

根据我的理解,可以在Dictionary中或在堆上进行分配.字典是否比C中的堆栈更快/更喜欢?但与C不同,没有范围和自动堆栈回收,所以我想知道是否只使用字典来表示全局数据结构(如果有的话).

就堆而言,它是否与C非常相似?堆管理是标准(ANS)概念,还是实现定义的?

Pet*_*sen 14

它不是Dictionary,也不是堆 - 堆的等价物是字典.然而,由于严重的限制,它更像堆栈而不是堆 - 在字典的末尾添加新单词(ALLOT由FORGET或FREE 分配和释放(但释放所有较新的单词 - 更像多个POP)) .

实现可以控制内存布局,从而实现传统的堆(或垃圾收集).一个例子是用于存储器管理的堆数据结构的A FORTH实现(1984).另一个实现是Quartus Forth的动态内存堆(2000).

很多是依赖于实现或扩展.例如,内存布局通常使用两个块缓冲区(位置BLOCKTIB),文本输入缓冲区和语言的值和低级/原始函数,在最低部分,中间的字典(向上成长)和返回堆栈和顶部1的参数堆栈.

字典上方第一个可用字节的地址返回HERE(它随着字典的扩展而变化).

字典上方还有一个暂存区(PAD返回的地址),用于临时存储数据.暂存区域可视为空闲内存.

首选操作模式是尽可能多地使用堆栈而不是局部变量或堆.

1 p.286(关于特定版本的Forth,MMSFORTH)在"FORTH的记忆,词典和词汇"章节中,Forth:文本和参考.Mahlon G. Kelly和Nicholas Spies.国际标准书号0-13-326349-5/0-13-326331-2(pbk.).1986年由Prentice-Hall.


小智 11

基本问题可能没有以新Forth用户需要的方式得到解答,因此我将对其进行操作.

Forth中的内存可能非常依赖于目标,因此我将描述限制为最简单的模型,即平坦的内存空间,其中代码和数据快乐地生活在一起.(与分段存储器模型相反,或者用于代码的FLASH存储器和用于数据或其他更复杂模型的RAM)

字典通常从内存的底部开始,由Forth系统向上分配.在一个简单的系统中,这两个堆栈将存在于高内存中,并且通常有两个CPU寄存器指向它们.(非常依赖系统)

在最基本的层面上,只需通过更改字典指针变量的值来分配内存.(有时称为DP)

程序员通常不直接访问此变量,而是使用一些更高级别的单词来控制它.

如上所述,Forth一词'HERE'返回字典空间中的下一个可用地址.没有提到的是HERE是通过获取变量DP的值来定义的.(系统依赖性,但对描述有用)

在Forth'HERE'可能看起来像这样:

:HERE( - addr)DP @;

而已.

为了分配一些记忆,我们需要向上移动,我们用'ALLOT'这个词来做.

'ALLOT'的Forth定义只是从参数堆栈中取一个数字,并将其添加到DP中的值.所以它只不过是:

:ALLOT(n - )DP +!; \'+!' 将n添加到内容变量DP

当我们创建一个新定义时,FORTH系统会使用ALLOT,以便我们创建的内容安全地存储在"ALLOTed"内存中.

一些不是很明显的东西是ALLOT可以采用负数,因此可以向上或向下移动字典指针.所以你可以分配一些内存并像这样返回:

HEX 100 ALLOT

然后像这样释放它:

HEX -100 ALLOT

所有这些都说明这是Forth系统中最简单的内存管理形式.在"BUFFER:"一词的定义中可以看到如何使用它的一个例子.

:BUFFER:(n - )创建ALLOT;

'BUFFER:'"在字典中创建"一个新名称(创建使用分配为名称留出空间)然后在名称和您的Forth系统可能使用的任何相关管家字节之后分配n个字节的内存

所以现在要分配一个命名内存块我们只需输入:

MARKER FOO \标记内存现在结束

HEX 2000 BUFFER:IN_BUFFER

现在我们有一个名为IN_BUFFER的8K字节缓冲区.如果想要在标准Forth中回收该空间,我们可以输入'FOO',并且FOO之后在Dictionary中分配的所有内容都将从Forth系统中删除.

但如果您想要临时存储空间,那么"HERE"以上的所有内容都可以免费使用!

所以你可以简单地指向一个地址并使用它,如果你想这样

:MYMEMORY这里200 +;\MYMEMORY指向HERE上方未分配的内存

                        \ MYMEMORY moves with HERE. be aware.
Run Code Online (Sandbox Code Playgroud)

MYMEMORY HEX 1000 ERASE \用2K字节的零填充它

Forth通常用于高性能嵌入式应用程序,其中动态内存分配可能导致不可靠的代码,因此使用ALLOT的静态分配是首选.然而,更大的系统有堆并使用ALLOCATE,FREE AND RESIZE就像我们在C中使用malloc等一样.

BF