You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi 10.2中未调用Free使用TStopWatch是否会引发内存泄漏?

关于Delphi 10.2 Tokyo中TStopWatch的内存泄漏疑问与正确用法指南

先给你吃个定心丸:你完全不用担心内存泄漏的问题,TStopWatch的设计和类完全不同,根本不需要调用Free,也不会因为函数被调用数百次导致内存堆积。

核心原因:TStopWatch是记录类型,不是类

Delphi里的类型分两种核心类别:引用类型(比如类)和值类型(比如记录、整数、字符串等)。类的实例是在堆上分配的,需要手动调用Free来释放内存;但TStopWatch属于记录类型(record),默认情况下它是在栈上分配内存的——当你的函数执行完毕,栈上的所有局部变量(包括这个TStopWatch实例)都会被编译器自动清理,完全不需要你手动干预。

正如你看到的Delphi官方文档所说:TStopWatch不是类,但需要用StartNew或Create显式初始化——这里的初始化只是设置记录内部的计时状态,不是在堆上分配内存,和类的构造函数完全不是一回事。

为什么网站示例调用sw.Free是错误的?

那个网站的示例明显是误导,TStopWatch作为记录类型,根本没有Free方法,强行调用的话编译阶段就会报错。写这个示例的人大概率把TStopWatch当成了类类型来处理,忽略了它的本质是值类型。

你的场景下的正确用法

你的函数每次被调用时创建一个TStopWatch实例是完全合理的,不需要刻意复用单个实例——记录的创建和销毁开销极低,完全不会影响性能。下面给你两种常见的正确用法:

1. 快速启动计时:用StartNew

这是最常用的方式,一行代码完成初始化并启动计时:

procedure YourTimedFunction;
var
  StopWatch: TStopWatch;
begin
  StopWatch := TStopWatch.StartNew;
  
  // 这里放你需要计时的业务代码
  PerformHeavyOperation;
  
  // 获取耗时,支持多种时间单位:Ticks、Milliseconds、Seconds等
  Writeln('操作耗时:', StopWatch.ElapsedMilliseconds, ' 毫秒');
end;

2. 灵活控制启停:手动初始化+启停

如果需要分段计时,或者需要控制启停时机,可以用Create初始化,再手动调用Start/Stop/Reset:

procedure YourMultiStageFunction;
var
  StopWatch: TStopWatch;
begin
  StopWatch.Create; // 显式初始化记录状态
  
  // 第一段计时
  StopWatch.Start;
  DoFirstTask;
  StopWatch.Stop;
  Writeln('第一阶段耗时:', StopWatch.ElapsedMilliseconds, 'ms');
  
  // 重置后开始第二段计时
  StopWatch.Reset;
  StopWatch.Start;
  DoSecondTask;
  StopWatch.Stop;
  Writeln('第二阶段耗时:', StopWatch.ElapsedMilliseconds, 'ms');
end;

额外注意点

  • 永远不要尝试调用StopWatch.Free,这是完全错误的,编译器会直接报错。
  • 如果把TStopWatch作为类的字段(此时它会和类实例一起在堆上分配),也不需要单独释放,当类实例被Free时,它的字段会被自动处理。
  • TStopWatch的计时精度依赖系统的高精度计时器,在Windows平台上是非常可靠的,适合绝大多数性能测试场景。

内容的提问来源于stack exchange,提问作者blackcanopus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:05:17