Delphi:TAdoQuery 内存泄漏?
我正在使用 Delphi 5 和 ADO 开发一个小型糖尿病程序。我做了一个像这样的小查询:
function GetLowestGlucoseLevel(StartDate:string;EndDate:string): Integer;
var
Q:TADOQuery;
begin
try
Q:=TADOQuery.Create(Application); //Separate unit, owner set to App
Q.Connection:=dtMod.ADOCon;
Q.DisableControls;
Q.Close;
Q.SQL.Clear;
Q.SQL.Add('SELECT Min(qGlucose.Glucose) AS MinOfGlucose from qGlucose');
Q.Parameters[0].Value:=StartDate;
Q.Parameters[1].Value:=EndDate;
Q.Open;
Result:=Q.FieldByName('MinOfGlucose').AsInteger;
Q.Close;
finally
Q:=nil;
Q.Free;
end;
end;
查询运行正常并按预期返回结果。然而,当我检查Windows任务管理器时,查询后内存使用量不断上升而不是下降。
如何解决这个问题?
谢谢!
I'm developing as small diabetes program using Delphi 5 and ADO. I do a little query like this:
function GetLowestGlucoseLevel(StartDate:string;EndDate:string): Integer;
var
Q:TADOQuery;
begin
try
Q:=TADOQuery.Create(Application); //Separate unit, owner set to App
Q.Connection:=dtMod.ADOCon;
Q.DisableControls;
Q.Close;
Q.SQL.Clear;
Q.SQL.Add('SELECT Min(qGlucose.Glucose) AS MinOfGlucose from qGlucose');
Q.Parameters[0].Value:=StartDate;
Q.Parameters[1].Value:=EndDate;
Q.Open;
Result:=Q.FieldByName('MinOfGlucose').AsInteger;
Q.Close;
finally
Q:=nil;
Q.Free;
end;
end;
The query runs OK and returns the result as expected. However, when I checked Windows Task Manager, memory usage keeps on rising rather than decreasing after the query.
How to fix this?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您首先将
TADOQuery
设置为 nil,然后对 nil 变量调用Free
(这不会执行任何操作),从而泄漏了TADOQuery
You are leaking the
TADOQuery
by first setting it to nil, and then callingFree
on the nil variable (which does nothing)RTM ADO 实现众所周知
有问题。
Delphi 5 也是如此,并告诉您更多
关于泄漏的地方。
RTM ADO implementation is known to
have issues.
Delphi 5 as well, and tell you more
about where the leaks are.
德尔福方式:
The Delphi way:
引用:
你在开玩笑吧?首先将变量置零,然后释放它?你真是个天才! :-)
使用:
或者甚至不必为它分配 nil,因为 Q 是一个局部变量...
但是重新阅读您的代码,我注意到您使用 Application 作为所有者。因此,它实际上不会是泄漏,因为它会在应用程序被释放时被释放。如果您使用表单,则当所有者表单被释放时,它也会被释放。
您应该尝试调用此查询大约 100.000 次,以检查它是否继续保留内存,或者是否只是增加内存直到达到特定大小。后者更有可能,因为内存是为将来的 ADO 调用保留的。
Quote:
You're kidding, right? First nil the variable, then free it? You're a genius! :-)
Use:
Or don't even bother assigning nil to it, since Q is a local variable...
But rereading your code, I notice you use Application as owner. As a result, it will not really be a leak, since it will be freed when the application is freed. If you use a form, it would be freed when the owner form gets freed.
What you should try is to call this query about 100.000 times to check if it keeps reserving memory or if it's just increasing memory until a certain size has been reached. The latter is more likely, since the memory is reserved for future ADO calls.
正如其他人指出的那样,finally 部分应该颠倒 2 个语句,如下所示:
或者您可以调用 SysUtils.FreeAndNil(Q) (如果在 Delphi 5 中可用,不确定)。
除此之外,任务管理器对于确定内存使用情况来说是一个糟糕的工具。您可能会释放 Q 的内存,但这并不自动意味着 Delphi 内存管理器将内存释放给操作系统。
As others pointed out, the finally section should have the 2 statements reversed, like so:
Or you can call SysUtils.FreeAndNil(Q) (if that is available in Delphi 5, not sure).
Beside that, the TaskManager is an awful instrument to determine memory usage anyway. You might release the memory for Q, but that does not automatically mean the Delphi memory manager releases the memory to the OS.
除了将行反转为 Arjan 之外,jasonpenny 和 WorkShop Alex说,你可以使用Process Explorer查看进程的实际内存消耗(私有字节)。任务管理器并不真正适合此任务,因为它仅显示进程的工作集。
Aside inversing the lines as Arjan, jasonpenny and WorkShop Alex said, you can use Process Explorer to see the real consumption of memory (Private Bytes) of the process. Task Manager is not really suited to this task, as it only shows the working set of the process.