编程C,C ++,Java,PHP,Ruby,图灵,VB
计算机科学加拿大 
编程C,C ++,Java,PHP,Ruby,图灵,VB  

用户名:   Password: 
 登记登记   
 图灵垃圾收集概念证明
指数 -> 编程,图灵 -> 图灵教程
查看上一个主题 可打印的版本下载主题利率主题订阅本主题私人信息刷新页面 查看下一个主题
作者 信息
TheCool1kevin




邮政发布: 2018年7月02日星期一10:21 PM  帖子主题:图灵垃圾收集概念证明

垃圾收集poc.

回来的几个巫术,我开始在我的游戏引擎上进行图灵,以及初步的2D物理引擎。对我来说很少,尊重是一种面向对象的编程语言,这意味着我可以将vector存储在物体中而不是单独的组件。哇!来自C#编程的背景,我不明白“清理自己的垃圾”的概念,发现“自由后免费”相当刺激和烦人。所以,我的研究开始了。我偶然发现了工作 铸造厂 他的工作运行时间操纵是令人惊叹的。以及这一点,垃圾收集器的可能性和想法在我的脑海中开始形成。

在我们开始之前,我会假设您对面向对象的概念进行了坚实的掌握,以及对指针和引用的牢固了解。本文旨在展示图灵语言最远的限制,没有实际的目标。

引言和问题

假设你想分配一个对象。在c中,你会做这样的事情:
C:
vec2_t * myvector = (vec2_t *) malloc(尺寸(vec2_t));

现在,运行以下代码,您将意识到该程序将迅速吞并大量内存,导致最终的崩溃:
C:
尽管(真的)
    vec2_t* myVector = (vec2_t *) malloc(尺寸(vec2_t));

但是,在Java或C#中,相同的代码不会崩溃程序 - 为什么?
C#:
尽管(真的)
    Vector2 myVector = 新的 Vector2();

在C中,每次循环运行时,程序都会分配一些空间 ,当堆耗尽内存时,它从操作系统请求更多,当操作系统运行 - 嗯,程序崩溃(过程有点简化)。这意味着每个 Malloc. 你打电话,你需要打电话 自由,使开发非常困难。想象一下,写作一个复杂的计划(说游戏引擎),你忘记在游戏循环中释放一些对象......祝你好运弄清楚记忆泄漏来自哪里!
这就是为什么 垃圾收集 存在 - 对像我这样的白痴(也许你)。期限 垃圾 指仍在内存中分配但不由程序使用的对象。
C#:
一个obja = 新的 A();
Obja =. 空值;

以上是垃圾的一个简单的例子。该程序创建一个新对象 obja.,然后继续将它设置为 空值。因此,在第二行之后,在第一行分配的对象变为垃圾,因为它不能再通过参考指针访问 obja.。一种 垃圾收集器 是一种自动内存管理的形式,收集器尝试回收垃圾占用的内存。听起来很简单,不是吗? 没有。

解决方案

解决方案是找出垃圾发生何时何地。然后我们可以标记和垃圾,并将其扫到垃圾桶。这是正确的命名 标记和扫描 algorithm.
在我们甚至开始标记垃圾之前,我们需要跟踪我们创建的每个对象。不幸的是,如果没有自定义对象创建例程,则不可行。 PoC代码提供了一种通过这方面的方式 新的 procedure.
图灵:
New(adr. : 发言,obj. : 欺骗 发言)

基本上要创建任何对象,可以:
图灵:
var. myinstance. : 未经选中 ^ myclass. New(addr.(myinstance.), MyClass)

这显着长于默认值:
图灵:
var. myinstance. : ^ myclass. 新的 myInstance

请注意未选中的指针的用法。
PoC创建例程在运行时注入代码以创建一个新对象(如图所示,无法正确执行方法),并通过调用将其注册到垃圾收集器 GC.

有2个检查GC将执行以确定指针是否已成为垃圾。
图灵:
TryMarkGarbage(idx. : )

图灵:
MarkStack(PTR. : )

注意这些是 绝不 由用户从外部调用 对象 module.
第一个检查相当简单。它检查对象指针的值是否已从对象创建期间分配的值更改。如果是这样,那么我们假设原始对象引用丢失,因此物体已成为垃圾。这在我们以前的例子中展示了这一点 obja.。本质上:
图灵:
var. myinstance. : 未经选中 ^ myclass. New(addr.(myinstance.), MyClass)
新的(addr.(myinstance.), MyClass)

在第1行之后,将分配给堆的对象,并且其地址将存储在其中 myinstance.。第二行后,创建一个新对象,并将其引用存储在其中 myinstance.因此,第一个参考丢失,并且物体变得垃圾。
第二个检查是 轻微地 更复杂。它利用过程和函数中变量的事实存储在图灵中的堆栈上。展示:
图灵:
A()
    var. Foo : := 0
    “较低的地址: ", addr.(Foo)
结尾 A
B()
    A()
    var. 酒吧 : := 0
    “较高的地址: ", addr.(酒吧)
结尾 B
var. Baz. : := 0
B()

可以看出,Addr(Foo)将在较低的地址上,而不是Addr(Bar)(因为x86堆栈向下增长而不是向上),这意味着如果变量处于更高的堆栈帧,则它将无法访问。但是,要利用此属性,我们必须确定堆栈的绝对顶部(即,最低可能的堆栈地址)是这样的,因此我们不会在我们程序的数据部分中不小心免费使用。我们可以在函数调用之前直接用变量近似此情况,如 Baz. 在这种情况下。因此给出了两个指针, PTR1,PTR2.,如果两者都高于 stack_top., 和 PTR1.< ptr2,然后ptr1是垃圾,否则ptr2是垃圾。好吧,基本上无论如何。

通过内部工作解释,我可以向您展示代码并解释演示:
//gist.github.com/TheCool1Kevin/58e870a5a7b0f8868e5c8304125c9da3

演示和poc

由于基于堆栈的GC的怪癖,大多数代码必须封装在一个 主要的 程序。这不应该是一个负担。 main.tu的基本骨架如下:
图灵:
进口 对象 “Objects.tu”
var. stack_lower_limit. : %需要,不要移动线路位置!
Main()
    Init(addr.(stack_lower_limit.)) %init gc.
    %主代码以下
    % 等等等等等等...
结尾 Main
主要的()

一个新的概念是 对象.sweepall() 称呼。这基本上执行所有变量的全局扫描。通常,通过Java和C#,将有一个GC Worker线程,每种GC Worker线程每次都经常进行全局扫描,但是,自如此糟透了,我们必须手动调用它。由于手动调用的东西令人烦恼,我尽力避免使用 对象.sweepall() 称呼。不依赖的测试 对象.sweepall() 呼叫会说 “没有扫描。”
在运行时,我知道堆中还有一个对象。 GC不会清除堆中的每个对象,只有大多数。在演示main.tu中,堆中的一个杂散对象是因为 Markstack() 只是叫做什么时候 新的() 被调用,因此堆栈不会清除,因为没有创建新对象。要在项目中启用GC,您只需将上面发布的GIST下载为ZIP文件,并将其提取到项目文件夹中。从那里,你可以使用 对象.tu. 模块创建和免费对象。请注意,您的主要计划 必须 按照上面的模板,您必须使用提供的自定义对象创建API。

编辑:添加了最后一个测试用例,证明我不是欺诈

部署和限制

为了使这个库可用,您必须实现一个非常重要的缺失功能。让我们展示:
图灵:
var. myinstance1. : 未经选中 ^ myclass. New(addr.(myinstance1.), MyClass)
var. myinstance2. := myInstance1
myinstance1. :=
对象.MarkandSweep.()
myinstance2 - > doStuff()

此代码将失败,因为MyInstance2将指代释放对象。为了使这是一个可行的库,我们必须跟踪对象引用和指针引用。所以,我们必须跟踪 myinstance2.myinstance1.。一个限制是不是允许的 var. myinstance2:= myinstance1,我们必须做些什么:
图灵:
var. myinstance2. : 未经选中^ myClass等式(myinstance2,myinstance1.)

在处理返回指针并将指针作为方法参数交易时,这会变得更加复杂。这可能是为什么GC在图灵中不能真正成为可能。
结束
再次,荣誉 铸造厂 为了他们的工作 opcodes.tu. 头爆炸

欢呼,凯文。 非常酷



Asd.png.
 Description:
运行演示
 Filesize:  108.21 KB
 Viewed:  2228 Time(s)

Asd.png.


赞助
赞助
赞助
赞助
从上一个显示帖子:   
   指数 -> 编程,图灵 -> 图灵教程
查看上一个主题 告诉一个朋友可打印的版本下载主题利率主题订阅本主题私人信息刷新页面 查看下一个主题

11  [ 1 Posts ]
跳到:   


Style:  
搜索: