聊聊RTL RTL的内存机制是主要亮点 RTL中的内存分配采用标准的WINAPI分配机制 内存管理生成的代码也是用的WINDOWS标准的内存管理机制 而采用RTTI访问已经生成的内存,可以做到其他面向对象编译器做到的动态 虚拟 等机制以上我是我在的一点 希望各位大虾一起近来讨论 多给我点指点 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 SydPink(敲坏10块键盘就能成高手)敲坏10个键盘真的能成为高手 我的是联想的 我敲了3年还不坏 回家我就诅咒他 :) 哈哈,我回头买10个键盘来敲,把它们敲坏!:PRTL,我不懂 还有就是RTTI的机制 大家都知道他是通过指针和内存块地址访问 但具体RTL中怎么实现希望高手能讲讲我回头会发一些我这些天看的代码中的点滴 希望大家共同讨论 共同学习 up 现在正在整理图形单元的 所以RTL的一直没有整理出来 等整理出来在具体详细的问题 希望我老了也能学uml,听课 不就顶一下吗,谢什么至于高手不高手的,请楼主不要太在意了,即使不是高手也可以给你讲课的所以,阿拉就简单给你讲讲,,,(以下内容可能只适用于Delphi7)1.现在主要对单元生成的顺序 和销毁的顺序上有点不明白 首先,所谓生成,我理解为initialization的代码,销毁则为finalization的代码 那么顺序的问题,就是这些unit的调用这些代码段的顺序了。 初步说,我们考察project文件,program p;usesbeginend. 在编译期,编译器为project(包括library)产生一个描述单元之间的引用关系的有向无环图,准确一点讲,是描述单元之间的interface一段相互之间引用的关系,比如unit unit1;interfaceuses Unit2;implementationend.对于这个单元的声明,产生一个unit2->unit1的边那么unit2.initialization先于unit1执行,2.RTTI的机制 大家都知道他是通过指针和内存块地址访问 但具体RTL中怎么实现 1.现在主要对单元生成的顺序 和销毁的顺序上有点不明白 首先,所谓生成,我理解为initialization的代码,销毁则为finalization的代码 那么顺序的问题,就是这些unit的调用这些代码段的顺序了。 我们考察project文件,program p;uses Unit1, Unit2;beginend. 一般的,编译器会尊重你指定的顺序,它认为Unit1必须优先于Unit2, 所以它将产生Unit1.Initialzation优先于 Unit2.initialization的代码,这和Delphi的name resolution的规则恰恰相反。这是一般情形。 对于单元之间存在引用的情况, 在编译期,编译器为project(包括library)产生一个描述单元之间的引用关系的有向无环图,准确一点讲,是描述单元之间的interface一段相互之间引用的关系,比如unit unit1;interfaceuses Unit2;implementationend.对于这个单元的声明,产生一个unit2->unit1的边那么unit2.initialization先于unit1执行, implemnation节的uses子句不会影响单元初始化的顺序. Delphi将project中所包含的所有单元的initialization按照这些规则组成一个表,由程序的入口(StartExe)按顺序调用。 销毁的顺序与初始化的顺序相反 2.RTTI的机制具体RTL中怎么实现类型信息分为静态类型信息和运行期的类型信息,RTTI就是运行期类型信息。对于所有的类型信息,都在编译期确定好,写入PE文件的text/code区域比如IntegerTypeInfo(Integer)返回一个编译器确定好的RVA地址,这是静态类型信息,那么什么是运行期类型信息呢?就是编译器不能确定的类型信息。这主要是源自于对象的多态性。var A: TAObject; A := ...;那我们怎么获得A的类型信息呢?虽然A声明为TAObject,但是由于多态性的原因,编译器不能立即返回指向TAObject的类型信息,所以,如果你尝试写下下面这样的代码, TypeInfo(A);编译器马上就不高兴了那么它是怎么解决的呢?Delphi通过对象的内存布局来实现对于任意一个类对象实例变量,(接口对象目前没有研究)它的实质是一个指针,指向一个内存块,这个内存块的第一个数据就是该对象实际的类的虚拟方法表的地址,内存块其余的部分是对象的实例数据而虚拟方法表的地址的负向偏移,就包含了类对象的类型信息。比如实例大小,类名,父类类型信息的地址,但是这些信息并不是规范化的,不符合一些期望PTypeInfo类型的函数的参数要求,真正的TTypeInfo数据,是一个编译期硬性编码的只读内存数据,它由一个地址给出,而这个地址就在虚拟方法表的地址的负向偏移的某个地方,对于目前的Delphi实现,这个地址是在虚拟方法表的地址的负向偏移vmtTypeInfo = -60;的地方所以class function TObject.ClassInfo()的实现是这样的 Result := PPointer(Integer(Self) + vmtTypeInfo)^;注意,因为是类方法,所以这个Self是类指针,也就是VMT本身的地址比如,要取得var Obj: TObject;声明中Obj的实际类型信息,我们实际可以这样获得 PTypeInfo(PPointer(Integer(PPointer(Obj)^) + vmtTypeInfo)^);类型信息还有很多内容,比如方法、属性数据是怎么布局的,方法表,接口表等等的内容,因为这个话题比较大,我就算做个引子了,而且Delphi的帮助以及很多书籍都有介绍VMT的内容以及布局方面的细节这我就不多说了楼主也可以具体参考System单元中关于TObject的实现,vmtXXXXX系列常量的定义,再结合TypInfo(D7 Only?)单元,基本就清楚了 其实DELPHI在本地化处理和代码出错方面做了比较多,这方面DELPHI真的不错 :)不过感觉VC的RTL也不错 做的也同样很不错,但就是因为MFC封装的不好导致RTL没有被发挥。Danny真是天生的天才,天时地利都适合他 :) 先结了 如果想继续对此关注的可以到http:\\ttch.blogone.net\ 使用delphi7开发看《Delphi 5 开发人员指南》??? 工作了,散分! 菜单界面里如何设置线性菜单? 对我来说:非常难的问题,请大家帮帮忙!!! 新手上路!有没有DELPHI做网页模版的例子。请指教。up有分 关于一个报表的问题竟然问了一周有余没有人帮我解决?? delphi中begin...End...如何设置成自动配对? 请问怎样制作DELPHI控件在控件面板上的图标? 一个小错误请帮忙看看!!!急 怎样让一个form紧贴着另外一个form? 招聘程序员 限广州 安静,告诉大家一个不幸的消息:从今天开始,我将和Delphi说“再见”。
RTL,我不懂
听课
即使不是高手也可以给你讲课的所以,阿拉就简单给你讲讲,,,(以下内容可能只适用于Delphi7)
1.现在主要对单元生成的顺序 和销毁的顺序上有点不明白
首先,所谓生成,我理解为initialization的代码,销毁则为finalization的代码
那么顺序的问题,就是这些unit的调用这些代码段的顺序了。 初步说,我们考察project文件,program p;
usesbegin
end. 在编译期,编译器为project(包括library)产生一个描述单元之间的引用关系的有向
无环图,准确一点讲,是描述单元之间的interface一段相互之间引用的关系,比如unit unit1;
interface
uses Unit2;
implementation
end.对于这个单元的声明,产生一个unit2->unit1的边
那么unit2.initialization先于unit1执行,
2.RTTI的机制 大家都知道他是通过指针和内存块地址访问 但具体RTL中怎么实现
首先,所谓生成,我理解为initialization的代码,销毁则为finalization的代码
那么顺序的问题,就是这些unit的调用这些代码段的顺序了。 我们考察project文件,program p;
uses
Unit1,
Unit2;
begin
end.
一般的,编译器会尊重你指定的顺序,它认为Unit1必须优先于Unit2, 所以它将产生Unit1.Initialzation优先于 Unit2.initialization的代码,
这和Delphi的name resolution的规则恰恰相反。这是一般情形。 对于单元之间存在引用的情况, 在编译期,编译器为project(包括library)产生一个描述单元之间的引用关系的有向
无环图,准确一点讲,是描述单元之间的interface一段相互之间引用的关系,比如unit unit1;
interface
uses Unit2;
implementation
end.对于这个单元的声明,产生一个unit2->unit1的边
那么unit2.initialization先于unit1执行, implemnation节的uses子句不会影响单元初始化的顺序. Delphi将project中所包含的所有单元的initialization按照这些规则组成一个表,由程序的入口(StartExe)按顺序调用。
销毁的顺序与初始化的顺序相反
比如Integer
TypeInfo(Integer)返回一个编译器确定好的RVA地址,这是静态类型信息,
那么什么是运行期类型信息呢?
就是编译器不能确定的类型信息。这主要是源自于对象的多态性。var
A: TAObject; A := ...;那我们怎么获得A的类型信息呢?
虽然A声明为TAObject,但是由于多态性的原因,
编译器不能立即返回指向TAObject的类型信息,
所以,如果你尝试写下下面这样的代码,
TypeInfo(A);
编译器马上就不高兴了那么它是怎么解决的呢?Delphi通过对象的内存布局来实现对于任意一个类对象实例变量,(接口对象目前没有研究)
它的实质是一个指针,指向一个内存块,
这个内存块的第一个数据就是该对象实际的类的虚拟方法表的地址,
内存块其余的部分是对象的实例数据而虚拟方法表的地址的负向偏移,就包含了类对象的类型信息。比如实例大小,类名,
父类类型信息的地址,但是这些信息并不是规范化的,不符合一些期望PTypeInfo类型
的函数的参数要求,
真正的TTypeInfo数据,是一个编译期硬性编码的只读内存数据,它由一个地址给出,
而这个地址就在虚拟方法表的地址的负向偏移的某个地方,对于目前的Delphi实现,这个
地址是在虚拟方法表的地址的负向偏移vmtTypeInfo = -60;的地方所以class function TObject.ClassInfo()的实现是这样的
Result := PPointer(Integer(Self) + vmtTypeInfo)^;
注意,因为是类方法,所以这个Self是类指针,也就是VMT本身的地址比如,要取得
var
Obj: TObject;
声明中Obj的实际类型信息,我们实际可以这样获得
PTypeInfo(PPointer(Integer(PPointer(Obj)^) + vmtTypeInfo)^);类型信息还有很多内容,比如方法、属性数据是怎么布局的,
方法表,接口表等等的内容,因为这个话题比较大,我就算做个引子了,而且Delphi的帮助以及很多书籍都有介绍VMT的内容以及布局方面的细节
这我就不多说了楼主也可以具体参考System单元中关于TObject的实现,vmtXXXXX系列常量的定义,
再结合TypInfo(D7 Only?)单元,基本就清楚了
http:\\ttch.blogone.net\