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