第一段:不出错是因为你把那个strstr做成了tform1里的一个成员。成员的初始化在对象的初始化里完成。所以,第二段当然会出错。
解决方案 »
- 如何对jpg图片进行CRC效验?
- delphi我要删除数据库中的数据这段代码哪里有问题
- 多线程程序里定义了一个对象,想在该对象的某个事件中写代码,怎样做?
- 如何制作像delphi的对象检查器一样的效果呢?
- 当TADOQuery所连接的TADOconnect进行重连之后,TADOQuery 是否一定要重新执行“Select ”语句??
- 已知某一窗口的句柄,用什么办法可以销毁它???
- 如何在Delphi程序中使用API函数?
- 图片的滚动问题
- Currency到Integer类型如何转换?
- 关于在access中数据类型是图片(OLE对象)的问题
- 如何知道哪一个控件的基类是什么
- 我想用delphi写一个音像出租管理系统,大家能不能帮帮我,我现在已点思路都没有
关于{}就是编译开关指示字。可以找object pascal参考书仔细看看。{$R *.DFM}的意思是编译所有以dfm(delphi form)文件,从那个文件里读窗口信息。再如{r icons.res}就是指示编译icons.res资源文件。
首先说明这不是注释,{$..}注意$符号,他一般作为告诉编译器需要什么!
{$R ..}一般作为资源文件声明
{$APPTYPE ..}告诉编译器是什么类型的工程
如{$APPTYPE CONSOLE}就是说明当前编译的是一个控制台程序
{$E ..}告诉编译器可以产生什么扩展名
{$E DEU}
{$E CPL}
还有很多,建议你看看帮助
2 :它是一个局部变量,在堆上分配,不清0,内容为内存里随机量,free时当然会有错误。
3 :set nil不能释放内存,但p.Free;后加p := nil;是一个好的习惯。
绝对不要直接p:=nil;因为这样它指向的内存并没有释放!
其他就如上面各位所说。
FillChar(X, SizeOf(X), 0)
这样的动作,所以第一个不会错。第二个,局部变量,Delphi是不负责为你初始化的,所以自然会出错啦。第三个,全局变量,同样是会在程序启动时被清空的。procedure tobject.free;
begin
if Self <> nil then
Self.Desroy; //明白为什么Destroy从TObject开始就是Virtual了吧
end;如果要确定在释放后设为Nil,则可以调用FreeAndNil
{$R filename}
{$RESOURCE filename}
The $R directive specifies the name of a resource file to be included in an application or library. The named file must be a Windows resource file and the default extension for filenames is .RES. To specify a file name that includes a space, surround the file name with single quotation s: {$R 'My file'}.
The * symbol has a special meaning in $R directives: it stands for the base name (without extension) of the source-code file where the directive occurs. Usually, an application抯 resource (.RES) file has the same name as its project (.DPR) file; in this case, including {$R *.RES} in the project file links the corresponding resource file to the application. Similarly, a form (.DFM) file usually has the same name as its unit (.PAS) file; including {$R *.DFM} in the .PAS file links the corresponding form file to the application.{$R filename.RES filename.RC} (where the two occurrences of 'filename' match) makes the .RC file appear in Delphi's Project Manager. When the user opens the .RC file from the Project Manager, the String Table editor is invoked.
When a {$R filename} directive is used in a unit, the specified file name is simply recorded in the resulting unit file. No checks are made at that point to ensure that the filename is correct and that it specifies an existing file.
When an application or library is linked (after compiling the program or library source file), the resource files specified in all used units as well as in the program or library itself are processed, and each resource in each resource file is copied to the executable being produced. During the resource processing phase, Delphi's linker searches for .RES files in the same directory as the module containing the $R directive, and in the directories specified in the Search path input box on the Directories/Conditionals page of the Project|Options dialog box (or in the directories specified in a /R option on the DCC32 command line).6.Delphi的光盘上有Documents目录,里面有Object Pascal的手册。也可以看联机帮助。
好像有这样一个规则:
一.在访问一个对象时首先要确定该对象的实例是否存在.
二.在程序中动态建立的对象,你要负责释放.
三.在释放一个对象后,最好把该对象的指针附成 nil.(好像这样更为安全)
四.对于Form在释放时建议(Borland这样建议)使用Release.
五.在程序中不要直接调用Desroy.*象上面的代码, 我不明白你为什么在使用TStrings时不先创建该对象的实例
(strs := TString.Creat),这样写程序很难想像!*对于全局变量编译器自动初始化,局部变量要程序员知己处理.
strstr.free;//strstr 再次被free,均会产生错误!the help say:free won't result an error even the object is nil实际上定义TstringList的一个实例就相当于定义了一个指针,你还没有create,就是说还没有分配内存空间,这只是个空指针。第二个指针同理。释放一个空指针是会出问题的。应该判断一下,如:if strstr <> nil then .......
你说的那个destory在哪里实现了呢?
asm
TEST EAX,EAX //if Self = nil then
JE @@exit // goto exit;
MOV ECX,[EAX] //
MOV DL,1 //
CALL dword ptr [ECX].vmtDestroy //call Self.Destroy;
@@exit:
end;
Delphi 6:procedure TObject.Free;
begin
if Self <> nil then
Destroy;
end;
真不好意思,我还想问一下, 你说的那个destory在哪里实现了呢? 我的意思是在vcl里,
好象tobject.destory是个空过程,(见笑了),其实这道问题是我自定义的一个class(tobject)中产生的,我也并没有实现destory.
还有,TEST EAX,EAX //if Self = nil then 这句是什么意思,难道test eax,eax 不相等吗?(汇编我只是略懂一二,我的基础还是ms51汇编基础。),说不定这是个有代表性的疑问,
在这里,先谢了,致以崇高的革命敬礼!!!!!!!!
在(1)中你将 strstr 声明为全局变量,全局变量在 Delphi 中,在程序初始化时被设成“零”状态的,也就是 strstr := nil ,而空指针调用 Free 方法是是不会发生异常的(注意没有);在(2)中你将 strstr 声明为局部变量,局部变量在默认时是不会自动清零的,这是它所指的地址是一个随机数,调用 Free 方法时,Free 方法企图去释放这个随机地址的内存,所以发生了异常;在(3)中结合以上讲述,你在注意一点,Free 方法并不会将指针自动清零,实际上指针还是指向原来的内存地址(只不过内存已经被释放),这时你再调用 Free 方法就是二次释放内存了,当然发生异常。
2.SET NIL 能够释放内存吗? 和free有什么区别?有没有别的办法?或者二选一?
一般的指针(包括普通对象),Set nil 是不能释放内存的,Set nil 仅仅是将指针所指的内存地址改变(这样就可能丢失了原来已经分配空间的地址)。Free 就是释放指针所指的内存,它内部调用了 VirtualFree win32 API 真正释放内存。但是其中有一个特殊(可以说是超常规的),就是接口对象 interface 的内存释放就是使用 Set NIL 的方法,其实也不奇怪,是 Delphi 编译器在幕后增加了代码。
3.'{$R *.DFM}'是什么?这些等等的含义是什么?用'{...}'做注释不会有干扰吧?
{$xxx} 是编译指令,具体含义你可以查帮助。所以你的注释就不要用 {$ 开头了。
Free 就是释放指针所指的内存,它内部调用了 VirtualFree win32 API 真正释放内存。
我有了一点感性认识了。请示意地给我讲一讲下面的代码,好吗?
procedure TObject.Free;
asm
TEST EAX,EAX //if Self = nil then
JE @@exit // goto exit;
MOV ECX,[EAX] //
MOV DL,1 //
CALL dword ptr [ECX].vmtDestroy //call Self.Destroy;
@@exit:
end;
这里的test,je,mov,call的作用我都还了解,请讲讲过程,行吗?
下面看看代码:
TEST EAX,EAX // 检查对象是否已经 =nil
JE @@exit // 如果对象已经 =nil,就退出,不做任何事,所以没有异常
MOV ECX,[EAX] // 取出函数入口表
MOV DL,1 //设标志,以后用到
CALL dword ptr [ECX].vmtDestroy // 也就是调用 Destroy 方法,现在你明白为什么最好不直接调用 Destroy 方法了吧没多神秘吧 :)
其中开头的一些是固定,像Destroy方法就是其中一个,因为Destroy方法声明的时候是声明成Destructor的,所以编译器会自动在这里
加上释放内存的代码,真要想看的话,方法如下:Projects --> Porject Option --> Compiler --> Debuggin --> Use Debug DCUs
打勾,然后一直按F7,就可以了。至于汇编,我也基本上不会,:(
所以,也要让qkl来解释了。
strstr:tstrings;
destructor myclass.free;
end;
destructor myclass.free;
strstr.free;
inherited free;
end;请大家指正,老有错误!
begin //******
strstr.free;
inherited free;
end;
strstr.free 没有Creat就Free,不妥吧。
对不起,上面我没有将源程序具体列举出来,语法应不存在错误。
***********************************
type myclass=class
strstr:tstrings;
public
...//这里我省略了其它一些过程,及成员声明。
destructor myclass.free;//只讨论free 过程。
end;destructor myclass.free;
begin
strstr.free;//在constructor中我已将它create了而且也没有将在任何其它的过程中free掉。
inherited free;
end;
调用free会产生错误。
在运行时会产生错误.
请高手不啬指正。!!谢谢。
我想问题可能不是Free,而是在于你用的TStrings,它有很多抽象方法和虚方法,你应该使用TStringList.
在每次释放时用下面的语句:
if assigned(strlst) then
begin
strstr.free;
strstr:=nil;
end;解释:当把它释放掉以后,指针还是指在老地方,所有要令它为nil,收回指针。
你的 strstr 单单是存放 string 型的变量吗?
你的程序是多线程方式吗?
既然是邮件服务器,不是多线程,怕是完成不任务!而且是非阻塞式的。
strstr:tstrings;
public
...
destructor destroy; override;
end;destructor myclass.destroy;
begin
strstr.free;//在constructor中我已将它create了而且也没有将在任何其它的过程中free掉。
inherited;
end;var myobj: MyClass;这样当你调用myobj.Free时,它用调用TObject.Free方法。如果myobj不为nil,则它会调用MyClass.destroy; 而MyClass.destroy中又调用了TObject.Destroy。调用顺序如下:myobj.Free; --> TObject.Free --> MyClass.Destroy --> TObject.Destroy。这就保证了每个析构函数的调用。如你所写的,假如
var
myobj: TObject;myobj := MyClass.create;myobj.Free; // 这里将调用TObject.Free,但不会调用MyClass.Free,因为TObject.Free不是虚方法。
在使用前创建,不用的时候free;不要直接使用Tstrings类型的变量,详情见delphi的帮助