- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在Android中的表单上动态创建TEdit
:
edit := TEdit.Create(Self);
edit.Free
释放它,但是它仍然在表单上。
最佳答案
更新为10.4
Delphi 10.4 Sydney跨所有平台统一了内存管理,并删除了ARC编译器。换句话说,现在所有平台都遵循与Windows平台相同的内存管理规则。
经典(非ARC)编译器中的DisposeOf
与Free
经典编译器上的
DisposeOf
调用Free
并在功能上表现相同的DisposeOf
仅用于向后兼容,在首选使用Free
的新代码(不必与ARC编译器保持兼容性)中,首选DisposeOf
中没有被更改为Free
TComponent
后代对象时,应遵循两个规则:
DisposeOf
的
DisposeOf
后不久引用未超出范围的情况下,对象引用也应设置为nil
(在陷阱中进行详细说明)DisposeOfAndNil
方法可能很有吸引力,但是ARC使它比旧的
FreeAndNil
方法复杂得多,我建议使用纯
DisposeOf - nil
序列来避免其他问题:
Component.DisposeOf;
Component := nil;
尽管在许多情况下,即使不遵守上述规则,代码也可以正常运行,但此类代码非常脆弱,很容易被看似无关的地方引入的其他代码破坏。
DisposeOf
中断ARC。它违反了ARC
的黄金法则。任何对象引用都可以是有效的对象引用,也可以是nil ,并且引入了第三种状态-
放置了“僵尸” 对象引用。
DisposeOf
,就像只是解决Delphi特定框架问题的加法,而不是真正属于ARC本身的概念。
TComponent
类(及其所有后代)在设计时考虑了手动内存管理。它使用与ARC内存管理不兼容的通知机制,因为它依赖于破坏析构函数中的强引用周期。由于
TComponent
是Delphi框架所依赖的基本类之一,因此它必须能够在ARC内存管理下正常运行。
Free Notification
机制之外,Delphi框架中还有其他类似的设计适用于手动内存管理,因为它们依赖于破坏析构函数中的强引用周期,但是这些设计不适合ARC。
DisposeOf
方法可以直接调用对象析构函数,并使这些旧代码可以与ARC一起播放。
TComponent
的任何代码也会自动成为旧代码。
So what else does DisoseOf solve? It is very common among variousDelphi frameworks (VCL and FireMonkey included), to place activenotification or list management code within the constructor anddestructor of a class. The Owner/Owned model of TComponent is a keyexample of such a design. In this case, the existing componentframework design relies on many activities other than simple “resourcemanagement” to happen in the destructor.
TComponent.Notification() is a key example of such a thing. In thiscase, the proper way to “dispose” a component, is to use DisposeOf. ATComponent derivative isn’t usually a transient instance, rather it isa longer-lived object which is also surrounded by a whole system ofother component instances that make up things such as forms, framesand datamodules. In this instance, use DisposeOf is appropriate.
DisposeOf
时到底发生了什么,有必要知道Delphi对象销毁过程是如何工作的。
destructor Destroy
方法链Component.Free
->立即执行阶段
1 -> 2 -> 3
使用ARC编译器释放对象
Component.Free
或Component := nil
->减少对象引用计数,后跟 a)或 b)1 -> 2 -> 3
Component.DisposeOf
->立即执行1
阶段,当对象引用计数达到0时,稍后将执行2
和3
阶段。DisposeOf
不会减少调用引用的引用计数。TComponent
Free Notification
机制通知注册的组件特定的组件实例正在释放。被通知的组件可以在虚拟
Notification
方法中处理该通知,并确保清除了它们可能在销毁的组件上保留的所有引用。
Free Notification
析构函数中触发了
TComponent
机制,并且没有
DisposeOf
和析构函数的直接执行,两个组件可以相互保持强引用,从而在整个应用程序生存期内保持自身的生命。
FFreeNotifies
列表被声明为
FFreeNotifies: TList<TComponent>
,它将存储对任何已注册组件的强引用。
TEdit
和
TPopupMenu
并将该弹出菜单分配给edit的
PopupMenu
属性,则edit将在其
FEditPopupMenu
字段中强烈引用弹出菜单,而弹出菜单将在其
FFreeNotifies
列表中保留强烈引用以进行编辑。如果要释放这两个组件中的任何一个,则必须在它们上调用
DisposeOf
,否则它们将继续存在。
Menu.Free
替换为
Menu.DisposeOf
,则会触发
Free Notification
机制并破坏强引用周期。
procedure ComponentLeak;
var
Edit: TEdit;
Menu: TPopupMenu;
begin
Edit := TEdit.Create(nil);
Menu := TPopupMenu.Create(nil);
Edit.PopupMenu := Menu; // creating strong reference cycle
Menu.Free; // Menu will not be released because Edit holds strong reference to it
Edit.Free; // Edit will not be released because Menu holds strong reference to it
end;
DisposeOf的陷阱
DisposeOf
的实现方式,这还有两个主要问题。
DisposeOf
不会在调用引用
QP report RSP-14681时减少引用计数
type
TFoo = class(TObject)
public
a: TObject;
end;
var
foo: TFoo;
b: TObject;
procedure DoDispose;
var
n: integer;
begin
b := TObject.Create;
foo := TFoo.Create;
foo.a := b;
foo.DisposeOf;
n := b.RefCount; // foo is still alive at this point, also keeping b.RefCount at 2 instead of 1
end;
procedure DoFree;
var
n: integer;
begin
b := TObject.Create;
foo := TFoo.Create;
foo.a := b;
foo.Free;
n := b.RefCount; // b.RefCount is 1 here, as expected
end;
2. DisposeOf
不会清理实例内部托管类型引用
QP report RSP-14682
type
TFoo = class(TObject)
public
s: string;
d: array of byte;
o: TObject;
end;
var
foo1, foo2: TFoo;
procedure DoSomething;
var
s: string;
begin
foo1 := TFoo.Create;
foo1.s := 'test';
SetLength(foo1.d, 1);
foo1.d[0] := 100;
foo1.o := TObject.Create;
foo2 := foo1;
foo1.DisposeOf;
foo1 := nil;
s := IntToStr(foo2.o.RefCount) + ' ' + foo2.s + ' ' + IntToStr(foo2.d[0]);
// output: 1 test 100 - all inner managed references are still alive here,
// and will live until foo2 goes out of scope
end;
解决方法
destructor TFoo.Destroy;
begin
s := '';
d := nil;
o := nil;
inherited;
end;
上述问题的综合影响可能以不同的方式体现出来。从保留不必要的分配内存到难以捕获由所包含的非拥有对象和接口(interface)引用的错误,意外引用计数引起的错误。
DisposeOf
不会减少调用引用的引用计数,因此重要的是,在析构函数中对此类引用进行
nil
的引用,否则整个对象层次结构的存活时间可能比所需时间更长,有时甚至在整个应用程序生命周期中都可以存活。
DisposeOf
解析所有循环引用
DisposeOf
的问题是,只有在析构函数中有可解析循环引用的代码时,它才会中断循环引用-就像
TComponent
通知系统所做的那样。
[weak]
和/或
[unsafe]
属性来破坏不由析构函数处理的此类循环。这也是ARC的首选做法。
DisposeOf
用作打破所有引用周期(从未设计过的引用周期)的快速解决方案,因为它不起作用,滥用它可能导致难以跟踪的内存泄漏。
DisposeOf
不会破坏的循环的简单示例是:
type
TChild = class;
TParent = class(TObject)
public
var Child: TChild;
end;
TChild = class(TObject)
public
var Parent: TParent;
constructor Create(AParent: TParent);
end;
constructor TChild.Create(AParent: TParent);
begin
inherited Create;
Parent := AParent;
end;
var
p: TParent;
begin
p := TParent.Create;
p.Child := TChild.Create(p);
p.DisposeOf;
p := nil;
end;
上面的代码将泄漏子对象实例和父对象实例。结合
DisposeOf
无法清除内部托管类型(包括字符串)的事实,这些泄漏可能会很大,具体取决于您存储在内部的数据类型。打破这种循环的唯一(正确)方法是更改
TChild
类声明:
TChild = class(TObject)
public
[weak] var Parent: TParent;
constructor Create(AParent: TParent);
end;
关于android - 如何在Android/iOS中释放组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27818697/
我错过了什么,我已完成 的安装指南中要求的所有步骤 native 脚本 运行 tns doctor 给我以下输出... C:\abc\xyz>tns doctor √ Getting environm
尝试从 {addToCart(book)}}/>}> 传递数据至}> 问题: 购物车 ( render={()=> ) 收到 null,但没有收到我尝试发送的对象 已放置“console.log...
这是 _app.tsx 的外观: function MyApp({ Component, pageProps }: AppProps) { return } 我在构建项目时遇到了这个错误: Ty
我的 Laravel Vue 组件收到以下警告: [Vue warn]: Avoid mutating a prop directly since the value will be overwrit
根据这个example更详细this one我刚刚遇到了一件奇怪的事情...... 如果我使用方法作为 addTab(title,icon,component) 并且下一步想使用 setTabComp
目前我有一个捕获登录数据的表单,一个带有 TIWDBGrid 的表单,它应该返回与我从我的 mysql 数据库登录时创建的 user_id 关联的任何主机,以及一个共享数据模块。 下面是我的登录页面代
在我的react-native应用程序中,我目前有一个本地Android View (用java编写)正确渲染。当我尝试将我的react-native javascript 组件之一放入其中时,出现以
我为作业编写了简单的代码。我引用了文档和几个 youtube 视频教程系列。我的 react 代码是正确的我在运行代码时没有收到任何错误。但是这些 react-boostrap 元素没有渲染。此代码仅
几周前我刚刚开始使用 Flow,从一周前开始我就遇到了 Flow 错误,我不知道如何修复。 代码如下: // @flow import React, { Component } from "react
我想在同一个 View 中加载不同的 web2py 组件,但不是同时加载。我有 5 个 .load 文件,它们具有用于不同场景的表单字段,这些文件由 onchange 选择脚本动态调用。 web2py
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 6年前关闭。 Improve t
Blazor 有 InputNumber将输入限制为数字的组件。然而,这呈现了一个 firefox 不尊重(它允许任何文本)。 所以我尝试创建一个过滤输入的自定义组件: @inherits Inpu
我在学习 AngularDART 组件时编写了以下简单代码,但没有显示任何内容,任何人都可以帮助我知道我犯了什么错误: 我的 html 主文件:
我想在初始安装组件时或之后为 div 设置动画(淡入)。动画完成后,div 不应消失。我正在尝试使用 CSSTransition 组件并查看 reactcommunity.org 上的示例,但我根本无
我需要一个 JSF 组件来表示甘特图。是否有任何组件库(如 RichFaces)包含这样的组件? 最佳答案 JFreeChart有甘特图和PrimeFaces有一个图像组件,允许您动态地流式传输内容。
从软件工程的角度来看,组件、模块和子系统之间有什么区别? 提前致谢! 最佳答案 以下是 UML 2.5 的一些发现: 组件:该子句指定一组结构,可用于定义任意大小和复杂性的软件系统。特别是,它将组件指
我有使用非托管程序集(名为 unmanaged.dll)的托管应用程序(名为 managed.exe)。到目前为止,我们已经创建了 Interop.unmanaged.dll,managed.exe
我有一个跨多个应用程序复制的 DAL(我知道它的设计很糟糕,但现在忽略它),我想做的是这个...... 创建一个将通过所有桌面应用程序访问的 WCF DAL 组件。任何人都可以分享他们对关注的想法吗?
我有一个 ComboBox 的集合声明如下。 val cmbAll = for (i /** action here **/ } 所有这些都放在一个 TabbedPane 中。我想这不是问题。那么我
使用 VB6 创建一个 VB 应用程序。应用程序的一部分显示内部的闪存。 当我使用 printform它只是打印整个应用程序。我不知道如何单独打印闪光部分。任何帮助,将不胜感激!.. 谢谢。 最佳答案
我是一名优秀的程序员,十分优秀!