Memory management Forth中的内存管理

Memory management Forth中的内存管理,memory-management,heap,forth,Memory Management,Heap,Forth,所以我只是想了解一下,是否有人能帮我理解内存管理的工作原理。目前,我对C堆栈与堆范例只有(一些)经验 据我所知,可以在字典中或堆中进行分配。字典是否比C中的堆栈更快/更受欢迎?但与C语言不同的是,它没有作用域和自动堆栈回收,所以我想知道是否只对全局数据结构使用字典(如果有的话) 就堆而言,它很像C吗?堆管理是一个标准的()概念,还是定义了它的实现?它不是字典,或者在堆上-堆的等价物是字典。但是,由于其行为更像一个堆栈而不是一个堆,因此存在严重的限制—新单词被添加到字典的末尾(通过ALLOT分配,

所以我只是想了解一下,是否有人能帮我理解内存管理的工作原理。目前,我对C堆栈与堆范例只有(一些)经验

据我所知,可以在字典中或堆中进行分配。字典是否比C中的堆栈更快/更受欢迎?但与C语言不同的是,它没有作用域和自动堆栈回收,所以我想知道是否只对全局数据结构使用字典(如果有的话)


就堆而言,它很像C吗?堆管理是一个标准的()概念,还是定义了它的实现?

它不是字典,或者在堆上-堆的等价物是字典。但是,由于其行为更像一个堆栈而不是一个堆,因此存在严重的限制—新单词被添加到字典的末尾(通过
ALLOT
分配,通过遗忘或释放释放(但释放所有新单词—更像多个pop))

实现可以控制内存布局,从而实现传统的堆(或垃圾收集)。例如(1984年)。另一项实施是(2000年)

很多都依赖于实现或扩展。例如,内存布局通常有两个块缓冲器(位置由代码>块/<代码>和<代码> TIB < /代码>)、文本输入缓冲器和语言的值和低级/原始函数、最低部分、中间字典(向上生长)和返回堆栈和参数堆栈在前1。 字典上方第一个可用字节的地址由此处的
返回(它随着字典的扩展而改变)

字典上方还有一个草稿行区域(PAD返回的地址),用于临时存储数据。草稿行区域可视为可用内存

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


下午1点。286(关于福斯,MMSFORTH的特定版本)在“福斯的记忆、词典和词汇表”一章中,福斯:一个文本和一个参考。马龙·G·凯利和尼古拉斯是间谍。ISBN 0-13-326349-5/0-13-326331-2(pbk.)。有些Forth实现支持返回堆栈帧上的局部变量和分配内存块。例如:


彼得·莫滕森把它安排得很好。我将添加一些可能对C程序员有所帮助的注释

堆栈最接近C术语“自动”变量和通常称为局部变量的变量。您可以用FORTH来命名堆栈值,但大多数程序员都会尝试编写代码,这样就不需要命名值了

从C编程的角度来看,最好将字典视为“静态数据”。您可以在字典中保留地址范围,但一般情况下,您将使用ALLOCT和相关单词来创建静态数据结构和池,这些数据结构和池在分配后不会改变大小。如果要实现可实时增长的链接列表,可以为所需的链接单元格分配足够的空间,并编写文字以维护可从中提取的可用单元格列表。当然,这类东西也有实现,编写自己的实现是磨练指针管理技能的好方法

堆分配在许多现代Forth中都可用,标准定义了分配、释放和调整大小的字,这些字的工作方式类似于C中的malloc()、FREE()和realloc()。它们返回的内存来自操作系统堆,通常最好将地址存储在变量或比堆栈更永久的结构中,这样在释放指针之前就不会无意中丢失指针。作为旁注,如果发生错误,这些字(以及文件i/o字)在堆栈上返回非零的状态。此约定非常适合异常处理机制,并允许您编写如下代码:

variable PTR
1024 allocate throw PTR !
\ do some stuff with PTR
PTR @ free throw
0 PTR !
或者对于更复杂的(如果有点人为的)分配/自由示例:

\ A simple 2-cell linked list implementation using allocate and free
: >link ( a -- a ) ;
: >data ( a -- a ) cell + ;
: newcons ( a -- a )    \ make a cons cell that links to the input
   2 cells allocate throw  tuck >link ! ;
: linkcons ( a -- a )   \ make a cons cell that gets linked by the input
   0 newcons dup rot >link ! ;
: makelist ( n -- a )   \ returns the head of a list of the numbers from 0..n
   0 newcons  dup >r
   over 0 ?do
     i over >data ! linkcons ( a -- a )
   loop  >data !  r> ;
: walklist ( a -- )
   begin   dup >data ?  >link @           dup 0= until drop ;
: freelist ( a -- )
   begin   dup >link @  swap free throw   dup 0= until drop ;
: unittest  10 makelist dup walklist freelist ;

基本问题可能没有以一个新的Forth用户需要的方式得到回答,所以我将尝试一下

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

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

在最基本的级别上,只需更改dictionary指针变量的值即可分配内存。(有时称为DP)

程序员通常不直接访问这个变量,而是使用一些更高级的字来控制它

如前所述,第四个单词“HERE”返回字典空间中的下一个可用地址。这里没有提到的是,这里是通过获取变量DP的值来定义的。(此处为系统依赖性,但用于描述)

在Forth中,“此处”可能如下所示:

:此处(--addr)DP@

就这样

为了分配一些内存,我们需要在这里向上移动,我们使用“alloct”这个词

“ALLOT”的第四个定义只是从参数堆栈中获取一个数字,并将其添加到DP中的值。因此,这只不过是:

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

当我们创建一个新的定义时,第四个系统使用ALLOT,这样我们创建的内容就可以安全地放在“分配的”内存中

不明显的是,ALLOT可以取负数,因此可以上下移动字典指针。所以你可以
\ A simple 2-cell linked list implementation using allocate and free
: >link ( a -- a ) ;
: >data ( a -- a ) cell + ;
: newcons ( a -- a )    \ make a cons cell that links to the input
   2 cells allocate throw  tuck >link ! ;
: linkcons ( a -- a )   \ make a cons cell that gets linked by the input
   0 newcons dup rot >link ! ;
: makelist ( n -- a )   \ returns the head of a list of the numbers from 0..n
   0 newcons  dup >r
   over 0 ?do
     i over >data ! linkcons ( a -- a )
   loop  >data !  r> ;
: walklist ( a -- )
   begin   dup >data ?  >link @           dup 0= until drop ;
: freelist ( a -- )
   begin   dup >link @  swap free throw   dup 0= until drop ;
: unittest  10 makelist dup walklist freelist ;
                        \ MYMEMORY moves with HERE. be aware.