该死的clear 根本不释放内存,怎么才能释放泛型LIST的内存?
程序的内存一直不停的涨,用其他工具也查了有泄露但是是定位到进程创建的时候,总觉得很奇怪
后来查了资料
delphi的clear对内存是不释放的
因为我的程序在调用的很多 过程冲不断的clear,数据要不断的更新
clear的都是 tstringlist ,还有很多的结构体泛型的list,里面有string类型的,查看内存的时候 发现里面的内存一直不停的增长。问题是这样的
1 对于 tstringlist和泛型list应该怎样清理里面的数据 并且释放内存(释放里面的空间)。但是不需要重新去creat(不是彻底的把它销毁 还是可以使用这个泛型的list的,但是里面是空的,可以继续装数据进去),而且也不出现读写错误。
查资料的时候 发现 这么一段话
1
|
关于TList.Clear释放内存 一直以来被TList.Clear是否会释放每个Item的内存纠结,今天终于找到确切的答案了:不会释放,所以要释放每个Item指向的内存块,还是需要自己老老实实用循环Free掉或者Dispose掉
|
2、因为的我程序内存不停的涨,而且工具定位出来的位置都是在创建的地方,所以很难真正定位到泄露的位置,而且这些数据是希望程序真正退出之后才完全释放的。(中间有很多 clear add操作)应该怎么写?
分数有限,希望能够有人回复,只要解释清楚或者有代码说明就可以。
感谢回复。
Clear 只是清除了项中的内容,其中的对象并没销毁。请看DELPHI的实例:
procedure TForm1.FormButton1Click(Sender: TObject);
type
PMyList = ^AList;
AList = record
I: Integer;
C: Char;
end;
var
MyList: TList;
ARecord: PMyList;
B: Byte;
Y: Word;
begin
MyList := TList.Create;
try
New(ARecord);
ARecord^.I := 100;
ARecord^.C := 'Z';
MyList.Add(ARecord); {Add integer 100 and character Z to list}
New(ARecord);
ARecord^.I := 200;
ARecord^.C := 'X';
MyList.Add(ARecord); {Add integer 200 and character X to list}
{ Now paint the items onto the paintbox}
Y := 10; {Variable used in TextOut function}
for B := 0 to (MyList.Count - 1) do
begin
ARecord := MyList.Items[B];
Canvas.TextOut(10, Y, IntToStr(ARecord^.I)); {Display I}
Y := Y + 30; {Increment Y Value again}
Canvas.TextOut(10, Y, ARecord^.C); {Display C}
Y := Y + 30; {Increment Y Value}
end;
{ Cleanup: must free the list items as well as the list }
for B := 0 to (MyList.Count - 1) do
begin
ARecord := MyList.Items[B];
Dispose(ARecord);
end;
finally
MyList.Free;
end;
end;
跟进源码里看看就知道了啊
tstringlist从strings继承,strings 是个抽象类,clear是它的抽象方法,由其子类来负责实现clear,你可以自己覆盖clear,在其中做释放内存的工作,但顾名思义tstringlist只是string的容器,string和intert、double...这些简单类型一样,都是由系统维护它们的引用记录来自动管理其生命周期的,不用人为干预。
tlist的clear是个虚函数。
procedure TList.Clear;
begin // 基类实现中没有且也不应该负责清理item分配的内存
SetCount(0);
SetCapacity(0);
end;
你应该在其析构函数中处理item的内存清理工作,如果你要clear时也清理内存,就上面说的自己重写覆盖clear函数,在里面做清理。
我一般这样子释放:
for m := 0 to ls.Count - 1 do
Dispose(PExit(ls[m]));
ls.Clear();
ls.Free();
如果List里面是指针的话,需要单独释放每个item内容,然后再clear
PExit是自己定义的么。我没找到这个函数的过程。
还有 Dispose 需要指针类型的,直接给结构体导致编译不通过
间接赋值再释放导致出现数据访问错误的问题。。
begin
ARecord := MyList.Items[B];
Dispose(ARecord);-----这里编译器提示 ARecord不是指针类型。delphi 2010的
end;
finally
MyList.Free;
end;
end;
弄个简单的重写Tlist.Clear满足你需求的例子(非泛型,当然泛型更是方便了)
另外俺不是撸大师,请教俺撸同学,要保证鲁棒性必须清晰把握对象的生命周期
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
// 继承Tlist并重写Clear方法
TMyList = class (TList)
public
procedure Clear; override;
end ;
// 自定义个类型做为item,测试用
TMyClass = class (TInterfacedObject)
public
FMeb: Integer ;
end ;
TForm1 = class (TForm)
btn1: TButton;
procedure btn1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
public
end ;
var
Form1: TForm1;
implementation
{ $R *.dfm}
var
li: TMyList;
procedure TForm1 . btn1Click(Sender: TObject);
var
m: TMyClass;
const
{ $J +} count: Integer = 0 ; { $J -}
begin
m := TMyClass . Create;
Inc(count, 1000 );
m . FMeb := count;
li . Add(m);
// 可以观察到li.count是否正常,且item内容是否正确访问到
Caption := Format( 'li.count=%d; li.items[li.count-1]=%d' , [li . Count, TMyClass(li . Items[li . Count - 1 ]).FMeb]);
//li.Clear; 销毁list所有item, 可去掉注释猛击按钮观察count的值始终为1,且也没有泄露内存
end ;
{ TMyList }
procedure TMyList . Clear;
var
I: Integer ;
begin
// 倒叙遍历items确保安全访问index
for I := Count - 1 downto 0 do
begin
// 通过多态销毁item
// 如果想使用 is、as 操作符,得实现Iinterface接口
TMyClass(Items[i]).Free;
end ;
inherited ;
end ;
procedure TForm1 . FormCreate(Sender: TObject);
begin
li := TMyList . Create;
end ;
procedure TForm1 . FormDestroy(Sender: TObject);
begin
li . Free; //销毁list自身,free中会调用析构函数destroy,destroy中调用了clear
end ;
end .
|
procedure TForm1 . FormButton1Click(Sender: TObject);
type
PMyList = ^AList;
AList = record
I: Integer ;
C: Char ;
end ;
var
MyList: TList;
ARecord: PMyList;
B: Byte ;
Y: Word ;
begin
MyList := TList . Create;
try
New(ARecord);
ARecord^.I := 100 ;
ARecord^.C := 'Z' ;
MyList . Add(ARecord); {Add integer 100 and character Z to list}
New(ARecord);
ARecord^.I := 200 ;
ARecord^.C := 'X' ;
MyList . Add(ARecord); {Add integer 200 and character X to list}
{ Now paint the items onto the paintbox}
Y := 10 ; {Variable used in TextOut function}
for B := 0 to (MyList . Count - 1 ) do
begin
ARecord := MyList . Items[B];
Canvas . TextOut( 10 , Y, IntToStr(ARecord^.I)); {Display I}
Y := Y + 30 ; {Increment Y Value again}
Canvas . TextOut( 10 , Y, ARecord^.C); {Display C}
Y := Y + 30 ; {Increment Y Value}
end ;
{ Cleanup: must free the list items as well as the list }
for B := 0 to (MyList . Count - 1 ) do
begin
ARecord := MyList . Items[B];
Dispose(ARecord);
end ;
finally
MyList . Free;
end ;
end ;
|
你这个代码是一个组件里面 这样写虽然可以完全释放,可是使用时间太短了
我的要求是在窗体创建的时候创建,窗体运行的时候 节约内存空间(free的话导致内存不断上升),不能导致内存泄露,窗体销毁的时候彻底释放空间。你这个创建和销毁只在一个组件里面,这样意义很小。我的目的是如果在调用的过程里面泛型数组动态的增加,又不停的clear(clear不真正的清理空间)的时候 能够真正的清理空间减少程序内存的占用,窗体销毁的时候能够真正的彻底的销毁泛型list,中间不出现没有找到指针这样的提示(应该是释放多次的缘故,有些在创建之后使用它就不会提示,有些创建之后不使用就提示,但是因为使用不使用是在软件里面的一个设置,)
还有鲁过的代码我看不明白。希望鲁过师傅+我关注,我们多聊聊。项目最后快收尾了。这个内存泄露的问题是最后的几个重要问题,对于项目的收尾和验收有重要意义。希望鲁过师傅多多帮助。
我用的是delphi 2010 而且我的 list是泛型的,没有办法那样释放
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
procedure TForm1 . FormDestroy(Sender: TObject);
var I: Integer ; begin // TForm1销毁时 销毁list
if Assigned(List) then
begin
for I := List . Count - 1 downto 0 do
begin
FreeMemory(list . Items[i]); -------这里提示编译不通过 要求是指针
// FreeAndNil(list); 放到下面
end ;
end ;
FreeAndNil(list);
end ;
这样,即便仅仅create,最后销毁也不会有漏网的
procedure TForm1 . FormCreate(Sender: TObject); var gl, gl2: pGamelist;
begin List := TList < pGamelist > .Create;
//gl := GetMemory(SizeOf(TGamelist));
//gl2 := GetMemory(SizeOf(TGamelist));
//gl^.sky := 1000;
//gl2^.sky := 2000;
//List.Add(gl);
// 添加两项
//List.Add(gl2);
end ;
|
categroyList.retainAll(categroyList);
categroyList.clear();
该死的clear 根本不释放内存,怎么才能释放泛型LIST的内存?相关推荐
- 联想拯救者y7000p加内存条_怎么给笔记本升级内存和硬盘 联想Y7000P加装内存和硬盘图文介绍...
一般目前新买的笔记本电脑,大都是标配8GB内存和单块固态硬盘,内存和硬盘容量适中,但对于一些制图设计.偏大型游戏,又或者对硬盘存储要求比较高的用户来说,显然就不太够用,这时候我们一般会通过升级内存和硬 ...
- 联想拯救者y7000p加内存条_笔记本怎么升级内存和硬盘 联想Y7000P加装内存和硬盘图文教程 (全文)...
一般目前新买的笔记本电脑,大都是标配8GB内存和单块固态硬盘,内存和硬盘容量适中,但对于一些制图设计.偏大型游戏,又或者对硬盘存储要求比较高的用户来说,显然就不太够用,这时候我们一般会通过升级内存和硬 ...
- python内存管理和释放_《python解释器源码剖析》第17章--python的内存管理与垃圾回收...
17.0 序 内存管理,对于python这样的动态语言是至关重要的一部分,它在很大程度上决定了python的执行效率,因为在python的运行中会创建和销毁大量的对象,这些都设计内存的管理.同理pyt ...
- sk_buff整理笔记(三、内存申请和释放)
承接上一篇blog--sk_buff整理笔记(二.操作函数),这篇是要来讲解下sk_buff结构的内存申请和释放函数.因为sk_buff结构是比较复杂的(并不是其本身结构复杂,而是其所指的数据区以及分 ...
- Python内存管理及释放
python话说会自己管理内存,实际上,对于占用很大内存的对象,并不会马上释放.举例,a=range(10000*10000),会发现内存飙升一个多G,del a 或者a=[]都不能将内存降下来.. ...
- linux内存cached手动释放
总有很多朋友对于Linux的内存管理有疑问,之前一篇linux下的内存管理方式似乎也没能清除大家的疑虑.而在新版核心中,似乎对这个问题提供了新的解决方法,特转出来给大家参考一下.最后,还附上我对这方法 ...
- C/C++动态二维数组的内存分配和释放
C语言: 1 //二维数组动态数组分配和释放 2 //数组指针的内存分配和释放 3 //方法一 4 char (*a)[N];//指向数组的指针 5 a = (char (*)[N])malloc(s ...
- 【C 语言】结构体 ( 结构体中嵌套一级指针 | 分配内存时先 为结构体分配内存 然后再为指针分配内存 | 释放内存时先释放 指针成员内存 然后再释放结构头内存 )
文章目录 一.结构体中嵌套一级指针 1.声明 结构体类型 2.为 结构体 变量分配内存 ( 分配内存时先 为结构体分配内存 然后再为指针分配内存 ) 3.释放结构体内存 ( 释放内存时先释放 指针成员 ...
- linux 内存清理 释放命令,Linux系统中的内存清理和释放命令总结
Linux内核代码量大.逻辑关系复杂,因此对内核中的错误进行追溯和调试一直以来都是一件既耗费时间又耗费精力的事情.接下来是小编为大家收集的Linux系统中的内存清理和释放命令总结,希望能帮到大家. L ...
- linux 用户进程结束后 malloc申请的内存会自动释放吗,进程退出后malloc的内存是否会被释放?
当一个进程退出后,不管是正常退出或者是异常退出,操作系统都会释放这个进程的资源.包括这个进程分配的内存,打开的文件等等. 内存泄露的前提是进程一直在运行:进程一旦退出,所占的整个虚拟内存都被销毁,所有 ...
最新文章
- 语义SLAM开源代码汇总
- java多线程系类:基础篇:10生产者消费者的问题
- python代码示例下载-python下xml解析库lxml最新版下载安装以及代码示例
- 12/100. Diameter of Binary Tree
- 2017.9.15 postgresql批量插入造成冲突后执行更新
- 如何让oracle用户不过期,Oracle用户密码设为不过期的两种方法
- java登录界面圆形头像_自定义圆形头像
- JavaScript【面向对象】-静态方法-私有方法-公有方法-特权方法
- (2021系统架构设计师)个人对于软考的一些总结
- C++题解:矩阵快速幂 求 斐波那契数列
- libmodbus 开发说明
- 使用 MitmProxy 玩爬虫的,这篇文章别错过了!
- python装在固态还是机械好_大容量与高性能SSD硬盘的比较
- 软酷优计划java考试复习题_软酷题
- PHP 使用FPDF 处理中文遇到的坑
- .Net 微信支付集成
- 苹果手机对html的要求,原神iPhone 8能玩吗?苹果手机最低配置要求一览
- 猎豹傅盛内部演讲:上市只是成人礼,猎豹要忘记过去
- 深耕技术的同时,别忘了走出自己的舒适区
- 分布式系统理论基础 - CAP
热门文章
- linux 性能测试 跑分,测试10秒钟,分析8小时,性能评估只看跑分可不够
- 李航 《统计学习方法》习题8.1
- My Sixty-Second Page - 斐波那契数列 - By Nicolas
- Firefox书签同步工具Xmarks
- 【读心术】之微表情——《Lie to me 》摘自百度百科
- 小程序 房租水电费记录管理_长租公寓管理系统-智慧公寓小程序
- 导致 Scan VIP 和 Scan Listener(监听程序)出现故障的最常见的 5 个问题 (文档 ID 1602038.1)
- PoE供电技术与应用
- python画椭圆形_Python易学就会(五)turtle绘制椭圆与递归
- MySQL排序缓冲区溢出([HY001]; error code [1038],Out of sort memory, consider increasing server sort buffer )