我正在阅读有关内存分配/释放的Gforth手册,这是我无法理解的。假设我分配了一块内存来保存四个整数,如下所示:
create foo 1 , 2 , 3 , 4 ,
然后,也许我分配了更多内存,也许也释放了一些内存,现在我想 deallocate foo
。我怎么做?执行foo free
并foo 4 cells free
导致错误。
我正在阅读有关内存分配/释放的Gforth手册,这是我无法理解的。假设我分配了一块内存来保存四个整数,如下所示:
create foo 1 , 2 , 3 , 4 ,
然后,也许我分配了更多内存,也许也释放了一些内存,现在我想 deallocate foo
。我怎么做?执行foo free
并foo 4 cells free
导致错误。
一种选择是使用forget foo
,但这将“取消分配”自定义以来定义的所有内容foo
,并且比 Gforth 没有实现它更糟糕。在 Gforth 中,您必须使用“标记”,但这也将还原标记之后发生的所有内容。
例如(我将展示将其输入 Gforth 解释器会得到什么,包括解释器的响应(用双星号表示)):
marker -unfoo **ok**
create foo 1 , 2 , 3 , 4 , **ok**
/ A test word to get the first thing in foo (1) back
: test foo @ . ; **ok**
test **1 ok**
-unfoo **ok**
foo
**:8: Undefined word
>>>foo<<<
Backtrace:
$7FAA4EB4 throw
$7FAB1628 no.extensions
$7FAA502C interpreter-notfound1**
test
**:8: Undefined word
>>>test<<<
Backtrace:
$7FAA4EB4 throw
$7FAB1628 no.extensions
$7FAA502C interpreter-notfound1**
该示例旨在说明这一点,foo
并且test
在您执行后都消失了-unfoo
。
这实际上是如何工作的可能是我移动了解释器作为最后添加到字典中的地址。-unfoo
将其移回foo
添加的地址之前,这相当于释放foo
.
Here is another reference for this Starting Forth,总体上来说它非常适合学习 Forth。
回应对此答案的评论:
这个问题非常相似,这个答案非常有帮助。这可能是 Gforth 文档中最相关的部分。
上面的链接解释了malloc()
和free()
的Forth 版本resize()
。
因此,在回答您最初的问题时,您可以使用free
但您释放的内存必须由allocate
or分配resize
。
create
将一个项目添加到字典中,因此如果您想要恢复内存,这并不完全是您想要的。我对此的理解可能不正确,因为在正常执行过程中您通常不会从字典中删除内容。
存储字符串的最佳方式取决于您想用它做什么。如果您不需要它在程序的生命周期内存在,您可以单独使用s"
它,因为它会返回一个长度和一个地址。
一般来说,我会说使用create
是一个很好的主意,但它确实有局限性。如果字符串发生变化,您将不得不为其create
创建一个新的字典条目。如果您可以设置字符串长度的上限,那么一旦您有了create
单词,您就可以返回并覆盖已为其allot
编辑的内存。
这是我给出的另一个答案,它给出了一个定义字符串单词的例子。
所以总而言之,如果您确实需要能够释放内存,请使用 Gforth 提供的堆方法(我认为它们在 Forth 标准中,但我不知道是否所有 Forth 都实现了它们)。如果你不这样做,你可以根据你的问题使用字典。
CREATE ALLOT 和 VARIABLE 词占用字典空间(在 ISO 93 标准中查找。)传统上,您可以
忘记 aap
,但删除了aap和每个定义晚于aap的定义,与 free() 完全不同。
在复杂的 Forth 之类的 gforth 中,这种简单的机制不再起作用。它相当于截断链表并重置分配指针(HERE/DP)
在 gforth 中,您必须使用 MARKER。在投入
MARKER aap
您可以使用aap删除aap和以后定义的单词。 MARKER很麻烦,重启你的 Forth 要容易得多。