无法释放 OleVariant 变量导致内存泄漏问题(200分)

  • 主题发起人 主题发起人 plenilune168
  • 开始时间 开始时间
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
我在用 OleVariant 变量作 Midas 的远程调用函数时,用 MemProof 检测发现系统关闭后有 OEL SysString 资源没有释放。
发现是把普通字符串值赋给 OleVariant 变量时,系统自动通过调用API函数 SysAllocStringLen 动态分配内存把字符串类型转为 WideString 所占用的内存没有释放。
我用了以下多种方法都无法释放掉内存
v:=Null
v:=UnAssigned
VarClear(v)
本来想尝试用 API 函数 SysFreeString 释放,但是不知道怎么写,而且好象是字符串赋给OleVariant时,被自动转换成WideString中间过程所产生的内存,不知道怎么释放。
----------------------------------------------------------------------
重新建了一个新工程,只定义了一个 OleVariant 变量,发现也会出现内存泄漏问题
var v:OleVariant;
begin
v:='123456';
v:=Null;
//没有作用,无法释放
v:=UnAssigned;
//没有作用,无法释放
VarClear(v);
//没有作用,无法释放
end;

各位有谁知道怎么弄
 
不会吧,我测试过了, 而且olevariant的变量我一直这样操作啊。
我用cnmemprof测试过了, 没有任何泄漏。 不管作为方法变量还是类成员,公共变量。都正确释放了。 造成泄漏是应该是你其他的程序吧。
 
:::::::::::::::::::::::::::::::::::::::::::::::::::::
2006-06-30 19:23:31
程序运行时间: 0 小时 0 分 3 秒。
可用地址空间: 1024 千字节
未提交部分: 1008 千字节
已提交部分: 16 千字节
空闲部分: 13 千字节
已分配部分: 2 千字节
地址空间载入: 0%
全部小空闲内存块: 0 千字节
全部大空闲内存块: 0 千字节
其它未用内存块: 13 千字节
内存管理器消耗: 0 千字节
内存对象数目: 0
:::::::::::::::::::::::::::::::::::::::::::::::::::::
2006-06-30 19:24:08
程序运行时间: 0 小时 0 分 2 秒。
可用地址空间: 1024 千字节
未提交部分: 1008 千字节
已提交部分: 16 千字节
空闲部分: 13 千字节
已分配部分: 2 千字节
地址空间载入: 0%
全部小空闲内存块: 0 千字节
全部大空闲内存块: 0 千字节
其它未用内存块: 13 千字节
内存管理器消耗: 0 千字节
内存对象数目: 0
:::::::::::::::::::::::::::::::::::::::::::::::::::::
2006-06-30 19:27:28
程序运行时间: 0 小时 0 分 1 秒。
可用地址空间: 1024 千字节
未提交部分: 1008 千字节
已提交部分: 16 千字节
空闲部分: 13 千字节
已分配部分: 2 千字节
地址空间载入: 0%
全部小空闲内存块: 0 千字节
全部大空闲内存块: 0 千字节
其它未用内存块: 13 千字节
内存管理器消耗: 0 千字节
内存对象数目: 0
三次测试结果。
 
就这么简单的程序
-------------------------------------------------------
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
var V:OleVariant;
begin
V:='123456';
Showmessage(V);
end;

end.

使用 MemProof 0.9.50 测试结果如下,注意 OLE SysString 一行,正好是6个字节
---------------------------------------------------------------------------------------------
Resourcees Resource Count Resource Size
---------------------------------------------------------------------------------------------
Area Item Current# Peak# CurrentSize PeakSize
---------------------------------------------------------------------------------------------
Errors Error 1 1 0 0
Pointers Live Pointer 0 247 0 10788
Memory Virtual Memory 1 2 4096 20480
Memory Local Heap 0 2 0 5692
OLE SysString 1 1 6 6
GDI Pen 0 1 0 0
GDI Brush 0 3 0 0
GDI Font 0 5 0 0
GDI Palette 0 1 0 0
User Window 0 4 0 0
User Icon 0 1 0 0
User Cursor 0 7 0 0
User Window DC 0 1 0 0
Kernel Event 0 1 0 0
Kernel Critical Section 0 19 0 0
Kernel Critical Section Enter 0 5 0 0
Registry Registry 0 1 0 0

列出详细可以看到
---------------------------------------------------------------------------------------------------------------------
# Kind Value Size Item API Name Module
---------------------------------------------------------------------------------------------------------------------
1 SysString 0014D044 6 SysAllocStringLen(123456?旕,6) SysAllocStringLen oleaut32.dll
 
似乎OleVariant不需要释放
 
不释放的话泄漏的内存就越来越多。
从跟踪上就可以看出,字符串在 OleVariant 中就是以 WideString 的类型存在的,而建立 WideString 是 Delphi 通过调用 API 函数 SysAllocStringLen 建立的,但是却没有相应的调用 SysFreeString
另外一项 Virtual Memory 无论如何都是无法释放干净,应该是Delphi的内存泄漏
但是 OleVariant 却是用的变量越多消耗的内存越多,都释放不了的
忘了说这个程序是 Delphi5 下调试的,也否是版本问题。
 
我刚试过 Delphi2006,一样简单的程序,也存在同样问题
OleVariant 无法释放,而且运行中 OLE SysString 最高占用从 Delphi5 的6字节变为12字节,估计中间转换时用,不过最后有6字节是被释放掉的
另外 Delphi2006最后也有 4096 的 Virtual Memory 无法释放,估计还是Delphi本身的问题。从比较也可以看出,Delphi2006运行所需的空间比Delphi5大得多, 1314800:20480

---------------------------------------------------------------------------------------------
Resourcees Resource Count Resource Size
---------------------------------------------------------------------------------------------
Area Item Current# Peak# CurrentSize PeakSize
---------------------------------------------------------------------------------------------
Memory Virtual Memory 1 2 4096 1314800
OLE SysString 1 2 6 12
GDI Pen 0 1 0 0
GDI Brush 0 2 0 0
GDI Font 0 6 0 0
GDI Palette 0 1 0 0
User Window 0 5 0 0
User Icon 0 1 0 0
User Cursor 0 7 0 0
User Window DC 0 1 0 0
Kernel Event 0 3 0 0
Kernel Critical Section 0 19 0 0
Kernel Critical Section Enter 0 4 0 0
Registry Registry 0 1 0 0
 
另外有一点奇怪,ClientDataSet 传数据也是通过 OleVariant,但是却没有发现内存泄漏,不知道它具体是怎么处理的。
正在研究 ClientDataSet 源代码
 
后退
顶部