Delphi-判断一个对象是否释放,改造官方的Assigned
直接上例子了,基础知识自己去了解,首先定义一个类:
TPerson = class
public
name: string;
age: Integer;
constructor Create(name: string; age: Integer);
end;
constructor TPerson.Create(name: string; age: Integer);
begin
Self.name := name;
Self.age := age;
end;
例子1,首先了解Free,仅仅是销毁堆中数据,栈中变量的值依然是堆中的地址:
procedure TForm3.btn1Click(Sender: TObject);
var
ps: TPerson;
begin
ps := TPerson.Create('小李', 10);
ps.Free; //这里调用Free,堆中的数据已经被释放,但是ps这个指针的值还是堆中对象的地址
if Assigned(ps) then //Assigned方法,当ps指针的值为nil的时候,才返回False,由于ps的值不为nil,这里显然会返回True
begin
mmo1.Lines.Add('yes');
mmo1.Lines.Add(ps.name); //这里产生了Av错误,原因是ps堆中的对象已经被释放
end else begin
mmo1.Lines.Add('no');
end;
end;


例子2,知道即使你不创建实例,Assigned依然是true;
procedure TForm3.btn3Click(Sender: TObject);
var
p: TPerson;
begin
//p不初始化,会自由随机分配一个地址和值,值也是原来的自由值,不一定是nil,通常都不是nil
if Assigned(p) then
begin
//只要p指针的值不是nil,这里就会返回true,所以是yes
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no');
end;
end;


例子3:对例子1进行改造,使用FreeAndNil,将堆中数据释放,同时将栈中指针的值变为nil;
procedure TForm3.btn3Click(Sender: TObject);
var
ps: TPerson;
begin
ps := TPerson.Create('小李', 10);
FreeAndNil(ps); //指针的值也变成nil了
if Assigned(ps) then
begin
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no'); //此时就自然到这里了
end;
end;



例子4,最后一个例子,得出官方的Assigned 不是我们需要的:
procedure TForm3.btn4Click(Sender: TObject);
var
ps, ps1: TPerson;
begin
ps := TPerson.Create('小李', 10);
ps1 := ps;
FreeAndNil(ps);
if Assigned(ps) then
begin
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no'); //ps指针的值是nil了,所以no
end;
if Assigned(ps1) then
begin
mmo1.Lines.Add('yes'); //ps1指针的值不是nil
//mmo1.Lines.Add(ps1.name); //这里就会报错,因为ps堆中的数据已经释放
end else begin
mmo1.Lines.Add('no');
end;
//显然上面不是我们要的结果,使用我们自己的函数
if AssignedEx(ps1, TPerson) then
begin
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no'); //由于ps1指向的堆中数据已经不存在,这里会no
end;
end;

好了综上得出官方的Assigned 有点简陋,不是我们需要的,引出我们的修改版:
/// <summary>
/// 判断实例释放释放
/// </summary>
/// <param name="AVar">实例变量</param>
/// <param name="className">实例类型</param>
function AssignedEx(AVar: TObject; AClass: TClass): Boolean;
begin
//首先判断变量指针的值是否为nil
if not Assigned(AVar) then
begin
Exit(False);
end;
//判断堆中的数据是否是当前类
try
//若AVar指向的堆中数据已释放,则这里调用.ClassName会AV异常
if AVar.ClassName = AClass.ClassName then
begin
Exit(True);
end else begin
Exit(False);
end;
except
//有异常说明堆中已经被释放掉了
Exit(False);
end;
end;
==========================================================
最后贴上全部测试代码:
全部测试代码
unit Unit3;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm3 = class(TForm)
mmo1: TMemo;
btn1: TButton;
btn2: TButton;
btn3: TButton;
btn4: TButton;
btn5: TButton;
procedure btn1Click(Sender: TObject);
procedure btn2Click(Sender: TObject);
procedure btn3Click(Sender: TObject);
procedure btn4Click(Sender: TObject);
procedure btn5Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TPerson = class
public
name: string;
age: Integer;
constructor Create(name: string; age: Integer);
end;
var
Form3: TForm3;
implementation
{$R *.dfm}
constructor TPerson.Create(name: string; age: Integer);
begin
Self.name := name;
Self.age := age;
end;
/// <summary>
/// 判断实例释放释放
/// </summary>
/// <param name="AVar">实例变量</param>
/// <param name="className">实例类型</param>
function AssignedEx(AVar: TObject; AClass: TClass): Boolean;
begin
//首先判断变量指针的值是否为nil
if not Assigned(AVar) then
begin
Exit(False);
end;
//判断堆中的数据是否是当前类
try
//若AVar指向的堆中数据已释放,则这里调用.ClassName会AV异常
if AVar.ClassName = AClass.ClassName then
begin
Exit(True);
end else begin
Exit(False);
end;
except
//有异常说明堆中已经被释放掉了
Exit(False);
end;
end;
procedure TForm3.btn1Click(Sender: TObject);
var
ps: TPerson;
begin
ps := TPerson.Create('小李', 10);
ps.Free; //这里调用Free,堆中的数据已经被释放,但是ps这个指针的值还是堆中对象的地址
if Assigned(ps) then //Assigned方法,当ps指针的值为nil的时候,才返回False,由于ps的值不为nil,这里显然会返回True
begin
mmo1.Lines.Add('yes');
mmo1.Lines.Add(ps.name); //这里产生了Av错误,原因是ps堆中的对象已经被释放
end else begin
mmo1.Lines.Add('no');
end;
end;
procedure TForm3.btn2Click(Sender: TObject);
var
p: TPerson;
begin
//p不初始化,会自由随机分配一个指针,指针的值也是原来的自由值,不一定是nil
if Assigned(p) then
begin
//只要p指针的值不是nil,这里就会返回true,所以是yes
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no');
end;
end;
procedure TForm3.btn3Click(Sender: TObject);
var
ps: TPerson;
begin
ps := TPerson.Create('小李', 10);
FreeAndNil(ps); //指针的值也变成nil了
if Assigned(ps) then
begin
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no'); //此时就自然到这里了
end;
end;
procedure TForm3.btn4Click(Sender: TObject);
var
ps, ps1: TPerson;
begin
ps := TPerson.Create('小李', 10);
ps1 := ps;
FreeAndNil(ps);
if Assigned(ps) then
begin
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no'); //ps指针的值是nil了,所以no
end;
if Assigned(ps1) then
begin
mmo1.Lines.Add('yes'); //ps1指针的值不是nil
//mmo1.Lines.Add(ps1.name); //这里就会报错,因为ps堆中的数据已经释放
end else begin
mmo1.Lines.Add('no');
end;
//显然上面不是我们要的结果,使用我们自己的函数
if AssignedEx(ps1, TPerson) then
begin
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no'); //由于ps1指向的堆中数据已经不存在,这里会no
end;
end;
procedure TForm3.btn5Click(Sender: TObject);
var
ps, ps1: TPerson;
begin
ps := TPerson.Create('小李', 10);
ps1 := ps;
FreeAndNil(ps);
if Assigned(ps) then
begin
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no'); //ps指针的值是nil了,所以no
end;
if Assigned(ps1) then
begin
mmo1.Lines.Add('yes'); //ps1指针的值不是nil
//mmo1.Lines.Add(ps1.name); //这里就会报错,因为ps堆中的数据已经释放
end else begin
mmo1.Lines.Add('no');
end;
//显然上面不是我们要的结果,使用我们自己的函数
if AssignedEx(ps1, TPerson) then
begin
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no'); //由于ps1指向的堆中数据已经不存在,这里会no
end;
end;
end.
Delphi-判断一个对象是否释放,改造官方的Assigned的更多相关文章
- Delphi中关于资源释放(Free,Relealse,FreeAndNil)
根据日常编程经验,得出一些Delphi中关于资源释放的体会. 假如有对象Obj为TObject类型: 1) Obj.Free直接释放资源后,调用OnDestroy事件,但是没有将Obj指针值置为Nil ...
- win10 uwp 如何判断一个对象被移除
原文:win10 uwp 如何判断一个对象被移除 有时候需要知道某个元素是否已经被移除,在优化内存的时候,有时候无法判断一个元素是否在某个地方被引用,就需要判断对象设置空时是否被回收. 本文告诉大家一 ...
- 2018-8-10-win10-uwp-如何判断一个对象被移除
title author date CreateTime categories win10 uwp 如何判断一个对象被移除 lindexi 2018-08-10 19:16:50 +0800 2018 ...
- java面试一日一题:如何判断一个对象是否为垃圾对象
问题:请讲下在java中如何判断一个对象是否为垃圾 分析:该问题主要考察对java中的垃圾回收,用什么方式去识别一个对象是垃圾: 回答要点: 主要从以下几点去考虑, 1.GC回收的是什么,回收发生在内 ...
- JS心得——判断一个对象是否为空
判断一个对象是否为空对象,本文给出三种判断方法: 最常见的思路,for...in...遍历属性,为真则为"非空数组":否则为"空数组" 2.通过JSON自带的. ...
- Delphi的分配及释放---New/Dispose, GetMem/FreeMem及其它函数的区别与相同
转载自:http://www.cnblogs.com/qiusl/p/4028437.html?utm_source=tuicool 我估摸着内存分配+释放是个基础的函数,有些人可能没注意此类函数或细 ...
- delphi.memory.分配及释放---New/Dispose, GetMem/FreeMem及其它函数的区别与相同
我估摸着内存分配+释放是个基础函数,有些人可能没注意此类函数或细究,但我觉得还是弄明白的好. 介绍下面内存函数前,先说一下MM的一些过程,如不关心可忽略: TMemoryManager = recor ...
- javascript-如何判断一个对象为数组
Q:如何判断一个对象是否为数组? A1:判断对象的constructor是否指向Array, 接着判断对应的特殊属性,如length,splice之类.这个很容易冒充. A2:使用instanceof ...
- delphi 判断是否出现滚动条
delphi 判断是否出现滚动条 if (GetWindowlong(Stringgrid1.Handle, GWL_STYLE) and WS_VSCROLL) <> 0 the ...
- 使用js判断一个对象是否为空 比如 obj={}
今天使用到js判断一个对象是否为空,js没有封装好的方法,这里最好的办法就是使用jquery里面的封装好的方法 $.isEmptyObject(obj)
随机推荐
- oppo和海康嵌入式软件工程师面经总结
目录 海康 一面(3.23,35min) 自我介绍 项目介绍 你做的这个项目遇到了那些问题,如何解决的? 移植uboot,只做了移植吗? 用的那个文件系统? 移植过程中,网卡驱动做了那些工作? 写过那 ...
- freeswitch的mod_xml_curl模块动态获取configuration
概述 freeswitch是一款简单好用的VOIP开源软交换平台. mod_xml_curl模块支持从web服务获取xml配置,本文介绍如何动态获取acl配置. 环境 centos:CentOS r ...
- C#设计模式06——适配器的写法
什么是适配器模式? 适配器模式是一种结构型设计模式,用于将现有接口转换为符合客户端期望的接口.适配器模式允许不兼容的类可以相互协作. 为什么需要适配器模式? 在实际开发中,经常会遇到需要复用一些已有的 ...
- 图片与Base64编码相互转换、优势分析和技术实现
在Web开发中,图片与Base64编码的相互转换是一个非常实用的技能.图片 Base64编码是将图片文件转换为字符串格式,以便于在网络上传输和存储.本文将详细介绍图片与Base64编码的转换方法,以及 ...
- 机器学习-无监督机器学习-SVD奇异值分解-24
[POC] 1. 奇异值分解的本质 特征值分解只能够对于方阵提取重要特征, Ax=λx λ为特征值 x为对应的特征向量 奇异值分解可以对于任意矩阵: 注意看中间的矩阵是一个对角矩阵,颜色越深越起作用- ...
- 为R Markdown配置TinyTex编译环境
技术背景 在前面一篇博客中,我们介绍了一些关于在Windows系统上安装R Studio来编写R Markdown,最后编译成Beamer的演示文档的过程.而在Windows系统的使用过程中发现,编译 ...
- 30-组合可编程逻辑器件-PLD
组合可编程逻辑器件 1.PLD的结构 1.1 结构 1.2 表示方法 实心点表示连接,但是不可编程 ×点表示连接,但是可以编程 2.编程技术 2.1 熔丝工艺 每个输入线连接二极管和保险丝 2.2 电 ...
- css - 隐藏body滚动条
body::-webkit-scrollbar{ display: none; }
- OpenKruise :Kubernetes背后的托底
本文分享自华为云社区<OpenKruise核心能力和工作原理>,作者:可以交个朋友. 一. 诞生背景 Kubernetes 自身提供的应用部署管理功能,无法满足大规模应用场景的需求,例如应 ...
- SpringMVC08——拦截器——2021-05-11
拦截器概述 SpringMVC的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并做相应的处理. 例如:进行权限验证.记录请求信息的日志.判断用户 ...