自动内存管理(gc),新的思路
创始人
2024-01-13 08:10:42

自动内存管理可分为静态管理和动态管理,编译原理书上说的是动态管理,即运行时的自动垃圾回收(gc)。作者认为垃圾这个词不雅,就换用了“自动内存管理”。静态管理的关键是,在编译阶段自动添加free函数。

静态管理能处理多数情况,少数不能处理的情况,交给动态管理,即运行时自动垃圾回收(gc)处理。

程序结构分为顺序、分支、循环。分别讨论。

1、顺序结构

在顺序结构的程序中,从p=malloc到use§画出生命线,如果有q=p,也要画出到use(q)的生命线。

p=malloc(100)
q=p
use(p)
//这里不能free(p),后边还要用到p的等价变量q
use(q)
//在这里free(p),因为p和q等价,free(q)也行

关于q=p有三种解释:
一、指针赋值

object* p=malloc(100)
object* q=p

二、内存块复制

memcpy(q,p,100)

三、对象复制
包括p的成员一起复制。如p有一个长度为20的成员。

memcpy(q,p,100)
memcpy(q.m,p.m,20)

制作指针p的等价变量,用的是第一个,指针赋值。

p=malloc(100)
use(p)
//在这里free(p),因为p即将被赋予新的值
p=malloc(50) //这个p是个新的变量
use(p)
//free(p)

在函数调用中,如果有return p,说明对应的内存块还要继续使用,不能free。

object* func()
{
p=malloc(50)
use(p)
return p
}

生命线画到调用func的那个函数里。

2、分支结构

在分支结构中,生命线要分别进入不同的分支。

p=malloc
if rand()>0.5use(p)
elsenot use(p)
//如果在之后没有use(p),就在分支内添加free(p)。

分支内部的,按顺序结构处理。分支还会结束,当分支结束后继续use的情况,在最后一次之后free

if a>0p=mallocuse(p)
elseq=mallocuse(q)//free(q),在这里释放q,和顺序结构中一样q=mallocuse(q)//free(q)
use(p)
not use(q)
//free(p)

3、循环结构

在循环结构中分配的内存,相当于顺序结构中的连续多个p=malloc,需要free。

for(i=0;i<2;i++)
{p=mallocuse(p)
}

这个循环相当于

p=malloc
use(p)
p=malloc
use(p)

与顺序结构中一样,需要free(p),具体怎样进行呢?有两种方案:
一、在循环体结束前free

for(i=0;i<2;i++)
{
p=malloc
use(p)
//free(p)
}

这是常规思路,但有时,需要在循环结束后继续使用循环体中的变量,这需要另一种方案:
二、在malloc之前free

for(i=0,p=NULL;i<2;i++)
{if(p!=NULL)free(p)p=mallocuse(p)
}
use(p)

这样一来,就能够在循环结束后继续use(p)了。

4

除了跟踪malloc的生命线,还可以跟踪变量的生命线。一种有意思的情况是,两个变量可以共用一块内存。如int和float都占4字节,某种情况下,它们共用4字节空间。

int a
float b
b=use(a)

这种情况下,a和b可共用一块内存,因为a和b的生命线并不重合。b=use(a)可以理解成对a进行一系列计算,并把结果保留到b中,以后也不再使用a了。这样一来,可以先释放a再分配b,又因为a和b大小相等,就成了它们两个共用一块内存了。

int a
t=use(a)
//释放a
float b //在这里分配b
b=t

5

对malloc和free的封装函数,需要给出源代码,或是给出描述文件,方便内存管理。

p=start()   //封装了malloc
use(p)
end(p)     //封装了free

如果不能自动添加封装了free的end函数,就只能靠gc了。
如果有start函数的源代码,当然可以追踪到malloc的调用情况。如果没有源代码,就需要描述文件,它应该是这样的:

start():p=mallocp.left=mallocp.right=malloc

有了函数的描述文件,就能在需要free(p)的时候,也能够自动调用free(p.left)free(p.right)。以前这需要手动写end(p),现在可以自动地执行这些了。

6

如何处理环状结构?

a=malloc
b=malloc
a.m=b
b.m=a

这道题出现在python的引用计数法,需要说明的是,python的del和C语言的free并不相同。del使得引用计数减一,如果为零就回收。free必然回收一块内存,对已经回收了的空间再次使用free将报错。
上述例子中,执行del a和del b后,两个内存块仍然存在。若执行free(a),需连带执行free(a.m),此时再次执行free(b)将报错。
看来,画张图是必须的,因为实际情况中,不会是这么简单的环状结构。

7

最简单的情况是顺序结构:

p=malloc
use(p)
//生命线延续至此,自动添加free(p)

更复杂的情况是:
一、指针被重新赋值

p=malloc
p=malloc

第二句给p赋予新的值,那么原始的值就丢失了,应该在此之前free掉旧的内存块:

p=malloc
free(p)  //这句是自动添加的
p=malloc

二、指针被复制给新的指针

p=malloc
q=p
use(p)
use(q)

q看作是p的等价指针,生命线延续到不再使用p和q之后。

p=malloc
q.m=p

q是一个结构体,或称作对象,这是指针复制的另一种形式。
一个简单的函数调用,相当于顺序结构。

main()
{p=mallocp=func(p)
}
func(o)
{use(o)return o
}

调用函数的过程隐含一个o=p,如上文,生命线要延续下去,直到不再使用o。又因为return o隐含一个p=o,所以,生命线继续延续到p之后。

8

比顺序结构复杂的,是分支结构和循环结构。从汇编语言层次分析,是cmp和jmp指令的组合。
jmp指令明显可以指定生命线的方向,或者说,生命线沿着jmp的方向而延续。
if(a>0){B}else{C}
这段C语言转换成汇编语言:

cmp a,0
jbe A10;小于等于时,跳转到C
{B}
A10:
{C}

因为跳转指令的存在,生命线覆盖了{B}和{C},并进一步延伸到C以后。

对于循环结构,有如下代码:
for(i=0;i<10;i++){B}
转换成汇编语言:

mov i,0
A20:
cmp i,10
jge A10
{B}
inc i
jmp A20
A10:
;后续代码

这段代码怎么读?若在{B}中包括malloc,那么生命线怎样延续?如果指针p在for循环之前出现,那么它的作用域可以延伸到for循环之后;如果指针p在语句块{B}内部出现,则它只延续到B结束。

p
for(...){...}
use(p)//这里可以使用pfor(...){
p
use(p)
}
//这里不能使用p

前文中的关于jmp指令对于生命线的延续问题,在这里并不存在。应该从C语言的层次考虑生命线,在汇编语言层次,规律不明显。

用生命线的方法处理malloc和指针变量。其中指针变量又包括p和o.m,有了p=malloc之后,p就是malloc的等价变量,这和q=p使q,p等价是一样的。

{p   //p是这个作用域中的变量func(p)use(p)
}//在这里清除p,这是变量的作用域。

变量的作用域结束后,连带的malloc也就需要free了。但由于一个malloc可以有多个指针,所以画张图出来描述它们之间的关系,是必不可少的。

9

关于函数的递归调用还没研究,在递归调用中,生命线呈现什么样子?似乎是这样的:递归调用的函数会在栈上留下痕迹,每调用一次就在栈上分配出一个“栈帧”,然后便是函数调用时传递参数的复制过程。对于复制过程导致的生命线变化前文已经讨论过了。

func(x)
{
y=use(x)
func(x)
}

这是一个递归调用。

函数的调用,需要处理好传参数和返回值,这是两个赋值操作,其他方面,没什么不同?

相关内容

热门资讯

苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
阿西吧是什么意思 阿西吧相当于... 即使你没有受到过任何外语培训,你也懂四国语言。汉语:你好英语:Shit韩语:阿西吧(아,씨발! )日...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
阿西吧是什么意思 阿西吧相当于... 即使你没有受到过任何外语培训,你也懂四国语言。汉语:你好英语:Shit韩语:阿西吧(아,씨발! )日...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...