【问题标题】:Freeing a global variable in delphi在delphi中释放一个全局变量
【发布时间】:2013-10-04 18:58:27
【问题描述】:

我知道不加选择地使用全局变量是不明智的。但是,我需要使用一个 - TStringList。我的问题是如何(以及在​​哪里)释放它?已搜索,但找不到任何相关文档。

谢谢。

【问题讨论】:

  • 完成后释放它。也许在最终确定块中。只有您知道所需的寿命。我最重要的提示是确保您在使用完之前不要释放它。当然,另一种解决方案可能根本不使用全局。
  • 我尝试了以下代码,但它给了我错误;最后在定稿部分:implementation {$R *.dfm} uses AnalysisOptions; var OutputFile: TStringList; initialization OutputFile := TStringList.Create; finalization OutPutFile.Free; end; procedure EstimateClick(Sender: TObject); begin // OutputFile.Add(...) end; ... procedure SaveClick(Sender: TObject); begin OutputFile.Save(...); end;
  • 称我为异端,但当您只在最终确定时释放它时,您不妨让它保持打开状态,因为无论如何程序关闭都会释放所有资源。 (是的,如果您也询问 FastMM4,它也会将其报告为泄漏,但实际上并非如此,只是 Windows 稍晚清理它,或者您稍早清理它)。如果你能早点做,那么清理很有用。
  • @Johan, I'm a pedant 即使你是对的 :-)
  • @Johan:如果您要在关机时泄漏对象,请使用 FastMM 注册该对象,这样它就不会被报告为泄漏。

标签: delphi


【解决方案1】:

这可以通过记住内存管理的基本原则来回答:the Single Ownership Principle。每个变量都应该有一个所有者,负责清理它。

创建TStringList 的任何代码也应该负责在适当的时间销毁它(如果它是全局变量,则将全局变量设置为nil)。那么你是在哪里创建的呢?

当我有全局变量时,通常代表重要资源,它们通常由管理整个程序的对象设置。它们在初始化时被创建,并在主对象的销毁过程中被清除。另一方面,如果您在单元的 initialization 部分中创建它,您会希望清理在同一单元的 finalization 部分中。

【讨论】:

  • 我在一个名为 Estimate 的过程中创建它并可以在那里释放它,但用户可能希望保存 TStringList 的内容。显然,如果我在 Estimate 过程结束时释放它,Save 过程(文件菜单中 Save 命令的 OnClick 过程)无法访问内容。是的,我可以在保存过程中释放它。但是,如果用户不想保存内容怎么办?它永远不会被释放。
  • @user1505202:这对您来说似乎是一个范围界定问题。如果它是附加到表单的某些代码的一部分,为什么这个 TStringList 不是表单对象的成员而不是全局对象?
  • 也许我在说全局时使用了错误的术语。我的意思是我已经在实现部分声明了 TStringList,然后在一个名为 Estimate 的过程中创建它。然后另一个名为 Save 的过程访问它以保存它。我在哪里释放它?
  • 在这种情况下,我可能会在您单位的finalization 部分释放它。但它仍然可能值得一看,看看您是否可以使其成为类的成员,无论是作为实例成员还是作为类 var。 (如果您使用的是 Delphi XE 或更高版本 - 或者可能是 D2010,不确定 - 您可以使用类构造函数和类析构函数设置和释放类变量。)
  • 在 Finalization 部分释放它是可行的。谢谢。我在放置这些部分时遇到了麻烦。我需要承认你们所有人——我该怎么做?顺便说一句,缺少一条评论 - 这是关键!
【解决方案2】:

TStringList 在initialization 中初始化时应该是安全的,在finalization 部分中是免费的。

作为建议,考虑将对全局变量的访问封装到一个函数中,这样您就可以将 var 声明移动到 implementation 部分并对其进行更多控制。

请注意,initializationfinalization 在其他情况下可能不合适。尤其是当涉及线程或需要LoadLibrary() / FreeLibrary() 调用时,最好在正常程序流程中使用专门的程序来执行此操作。 initializationfinalization 部分都在 Windows 阻止某些事情的状态下执行。

【讨论】:

  • 我从未在任何程序中使用过初始化和终结部分。我的研究似乎表明这些部分超出了任何程序。因此,如果我在 Initialization 部分创建 TStringList,我会在 Finalization 部分释放它吗?这是我的代码。 implementation {$R *.dfm} uses AnalysisOptions; var OutputFile: TStringList; initialization OutputFile := TStringList.Create; finalization OutPutFile.Free; end; 过程 TfrmHillSlopeRegr.mmuFileOpenClick(Sender: TObject);开始 // 结束;
  • 编译器不喜欢“;”在“结束”之后
  • David Heffeman、Mason Wheeler 和 JensG 的初步回答为我指明了正确的方向(使用初始化和完成部分)和 Lans 的评论(我认为这是名字,但我可以'再也找不到评论了!)是关键。我想感谢你们所有人的帮助,但不知道如何。
  • 是我。但是当我意识到全局变量不是最适合您时,我删除了我的评论。 (包含this hotfix)用于您评论中的代码。如果您需要在表单范围内访问变量,那么您希望将其声明为私有字段(如this example 所示)并在表单的OnCreate 中创建和销毁该变量的对象实例和OnDestroy 事件方法。
  • @TLama,感谢浮出水面!你的两个例子都非常有帮助。我使用了您的第一个示例,但看到第二个示例可能更好。虽然不知道如何承认你。
猜你喜欢
  • 2013-01-03
  • 2011-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-20
  • 1970-01-01
相关资源
最近更新 更多