DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: hebhanax
今日帖子: 49
在线用户: 15
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 inbreak (入侵) ★☆☆☆☆ -
盒子活跃会员
2023/3/15 16:09:08
标题:
FreeAndNil 的问题 浏览:1953
加入我的收藏
楼主: Type
  TMyClass=class
    procedure WriteLog(msg:string);
  end;

var MyClass:TMyClass;

implementation

//略

initialization
  MyClass:= TMyClass.Create;
finalization
  FreeAndNil(MyClass);  //报错Runtime error 216 at XXXXXX
end.


在 FreeAndNil 前加 If MyClass<>nil then  或是 If Assiaged(MyClass) then 问题仍然。


改成这样就正常:

finalization
  MyClass := nil;
  FreeAndNil(MyClass);  //正常

也就是说,,先要将 MyClass = nil;
----------------------------------------------
我是菜鸟,己经搞了十多年了,但是我仍然很菜。
作者:
男 baby_moon (孤心明月) ★☆☆☆☆ -
普通会员
2023/3/15 16:23:31
1楼: if assigned(MyClass) then
  FreeAndNil(MyClass);
----------------------------------------------
-
作者:
男 akai1203 (w-dins) ★☆☆☆☆ -
普通会员
2023/3/15 16:39:13
2楼: 是不是带了接口
----------------------------------------------
-把学习当信仰
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2023/3/15 16:54:25
3楼: 楼主先确定你的 TMyClass 是否就是如此简单的一个类。

还是你的类很复杂,只是在这里提问,发了一个简单的?
----------------------------------------------
-
作者:
男 inbreak (入侵) ★☆☆☆☆ -
盒子活跃会员
2023/3/15 20:25:18
4楼: 压缩包是 .7z 格式
此帖子包含附件:inbreak_2023315202518.rar 大小:4,043B
----------------------------------------------
我是菜鸟,己经搞了十多年了,但是我仍然很菜。
作者:
男 inbreak (入侵) ★☆☆☆☆ -
盒子活跃会员
2023/3/15 20:26:08
5楼: unit Unit4;

interface
uses system.SysUtils,vcl.Forms;


  var MyForm :TForm ;

implementation

{ TMyClass }


initialization
  MyForm := TForm.Create(Application);
finalization
  FreeAndNil(MyForm );  //报错Runtime error 216 at XXXXXX
end.

end.



unit Unit3;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs,Unit4;

type
  TForm3 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

procedure TForm3.FormCreate(Sender: TObject);
begin
  MyForm.show;
end;

end.
----------------------------------------------
我是菜鸟,己经搞了十多年了,但是我仍然很菜。
作者:
男 tuesdays (Tuesday) ▲▲▲▲△ -
普通会员
2023/3/15 21:15:04
6楼: 界面类不需要释放. 
Create(Application); 已经交给主类了
----------------------------------------------
delphi界写python最强, python界写delphi最强. 写自己的代码, 让别人去运行.
作者:
男 roadrunner (roadrunner) ★☆☆☆☆ -
盒子活跃会员
2023/3/15 22:04:05
7楼: 重复Free了
----------------------------------------------
-
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2023/3/16 1:29:25
8楼: Debuging....  RAD 11.3


procedure FinalizeUnits;  // System.pas unit, line 24035
...
  try
    while Count > 0 do
...
   TProc(P)(); ...     <... Frozen... when try "ReleaseObjectInstanceBlocks;" in System.Classes.pas, line 21618



// Solution:
-- Dont use "Application" as "owner" in MyFormXX.Create( ... )
or
-- Dont use "Free" if you are using  MyFormXX.Create( Application )


---------
{$R *.dfm}

var
  MyFormXXX: TForm;

initialization

// MyFormXXX := TForm.Create(Application); // not use "FREE"!!!

MyFormXXX := TForm.Create(nil);

finalization

MyFormXXX.Free;  // OK

end.
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2023/3/16 1:39:07
9楼: it will be +/- that way:

if Assigned( Obj ) = if your "Obj" is pointing for some valid memory address?



if  Obj = nil  = if your "Obj" is pointing to "some valid" on memory = has a valid obj ("value") there on address?
-- valid value: an object live!!!


var
  x: TForm;  // by default, when created = "NOT NIL"

procedure TForm1.Button1Click(Sender: TObject);
begin
  // test with comment:
  // x := TForm.Create(application);  <----
  // x := nil;   <----

  if Assigned(x) then
    ShowMessage('x is assigned');
  //
  if (x = nil) then
    ShowMessage('x is empty');
end;
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2023/3/16 10:06:48
10楼: 改成这样就正常:

finalization
  MyClass := nil;
  FreeAndNil(MyClass);  //正常

==========

你这样改当然正常,但其实并没解决问题。

你先让 MyClass := nil; 了,然后再去释放它。释放一个 nil 当然不会有问题。

但是,你的 MyClass 之前是指向一个 Object 的,你把 MyClass 指向一个 nil,并不表示原来的 Object 就不在了。而且后面你释放的是一个 nil,也不是释放了原来的那个 Object。

一个 Object 你可以看作是一大片内存,这个内存的分配,是由 Create 来分配的。而 Free 则是释放这个 Object 占据的内存。至于 MyClass 这个变量仅仅是个名字,原本它指向这片内存。如果你修改了 MyClass 的值,它就指向其它地方,但那片内存还在。
----------------------------------------------
-
作者:
男 roadrunner (roadrunner) ★☆☆☆☆ -
盒子活跃会员
2023/3/16 10:42:56
11楼: 就是在finalization之前已经被free过了一次的问题

你们猛给他贴代码没有用,得他自己去找前一个free藏在哪里
----------------------------------------------
-
作者:
男 roadrunner (roadrunner) ★☆☆☆☆ -
盒子活跃会员
2023/3/16 10:45:00
12楼: free了两次而自己不知道,说明这个对象的生命周期已经失控了, 这就只有自己回头去补代码逻辑的课, 好好理解一下到底自己干了些啥
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2023/3/16 11:09:23
13楼: 在之前,在哪里被释放了?

有个办法:给这个类,加上一个 BeforeDestory 事件。在这个事件方法里面写一个 ShowMessage('被释放啦')

然后在这里设置断点。
----------------------------------------------
-
作者:
男 doorkey (DoorKey) ★☆☆☆☆ -
盒子活跃会员
2023/3/16 12:59:27
14楼: MyForm := TForm.Create(Application);
你已经交给Application了呀, Free的事情, Application会帮你干了.

如果是MyForm := TForm.Create(nil); 才要自己手工Free
----------------------------------------------
QQ: 9717005 我的Blog:http://www.cnblogs.com/anydelphi/
作者:
男 inbreak (入侵) ★☆☆☆☆ -
盒子活跃会员
2023/3/16 14:47:40
15楼: 谢谢大家。我明白了。
既然 交给 application 就无需要自己 free 了。
----------------------------------------------
我是菜鸟,己经搞了十多年了,但是我仍然很菜。
作者:
男 keymark (嬲) ▲▲▲△△ -
普通会员
2023/3/16 15:33:25
16楼: mark知识点
----------------------------------------------
[alias]  co = clone --recurse-submodules  up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/>http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
男 roadrunner (roadrunner) ★☆☆☆☆ -
盒子活跃会员
2023/3/16 17:09:32
17楼: @inbreak
所以说,你在顶楼的提问帖里的代码,是根本不会出Runtime error的

你根本就没测试,强行编造了一个不存在的Runtime error然后试图让大家来解决

这种提问让人相当的不愉快
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2023/3/16 23:00:39
18楼: 我靠,我在 3 楼假设的问题,果然碰巧说中了。楼主搞了一段简化问题的代码出来,而那个代码又是没有问题的。然后一堆人在猜问题在哪里。

学会正确的提问,太重要了。否则大家浪费时间,问题还得不到解决。

不过楼主在5楼贴了那段代码,我也没留意,还在看着顶楼的代码在讨论

==========

5 楼那段代码的根本问题是:MyForm := TMyForm.Create(Application);

这里的 Create 后面跟的参数究竟是个什么?既然跟了参数,那就应该搞明白啊,不是照抄代码就完事的。不明白不理解,就会出莫名其妙的错误。

你如果去看这个 Create 的 Help 或者源代码,它是:

constructor Create(AOwner: TComponent); override;

这个 AOnwer 是什么意思?在帮助里面有句话:
The memory for the owned component is freed when its owner's memory is freed. 

这里其实就是:Application 就是这个 MyForm 的 Owner,是它的拥有者。
因此,只要 Application 一释放,Application 就会释放所有它拥有的东西。

因此,一个东西有了 Owner 也就是有了拥有者,这个东西程序员就不用考虑自己释放了。只要释放了它的拥有者就可以了。

比如你可以做一个这样的实验:

Form1 := TForm1.Create(Application);
Form2 := TForm2.Cretae(Form1);
Form3 := TForm3.Create(Form1);

这时候,如果你释放了 Form1,Form2 和 Form3 就会自动被释放了。

Form1 有了 Owner,我们可以不用考虑需要用代码去释放它。但是,我们可以用代码去释放它。只不过我们的释放代码,必须是在 Application 被释放之前。如果在之后,那就是释放一个已经不存在,已经被 Application 释放了的东西,那当然就会出错。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2023/3/16 23:15:56
19楼: 从调试的角度来看,你即便不知道这个 Owner 的意思,你也可以在 Form 的 OnDestory 里面写调试代码,就会知道它在你的 Free 代码之前已经被 Free 了。
----------------------------------------------
-
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2023/3/17 8:32:43
20楼: 应该是对象在进入finalization之前已经被释放了, 楼上的是正解.
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
男 hawke2e (hawke2e) ★☆☆☆☆ -
普通会员
2023/3/19 22:13:40
21楼: 这是很基础的delphi知识点,也是delphi比js python麻烦的地方,即使用delphi做个简单的东西,如果不知道这些知识点就会引起头痛。
js python没有这类麻烦,随便写,现在有chatgpt更方便。
如果软件复杂,那无论delphi还是其它,你都得掌握这些细节的东西;否则,你都不知道软件为什么会抛异常为什么出错,如果再加上没有足够的排错经验,基本意味着解决不了了,要寻求帮助。
不过,对于开发复杂而庞大的软件来说,这些都是非常次要的。
所以,我建议,这些知识点,对于初学者来说,碰到了不要问,自己找解决办法弄清楚。
----------------------------------------------
软件是什么,相信很多人都说不清。
作者:
男 supermay (supermay) ★☆☆☆☆ -
盒子活跃会员
2023/4/4 10:57:41
22楼: MyClass := nil;
都为nil了,后面一句还有用吗?这样当然不出错了
  FreeAndNil(MyClass);  //正常
----------------------------------------------
链接:https://pan.baidu.com/s/12jzmECYKhGCsHBxz8tmB6w 提取码:pelr --来自百度网盘超级会员V9的分享
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行70.3125毫秒 RSS