delphi程序变量Create之后不free 有什么影响?(讨论)

一剑飘雪 2012-06-07 04:58:41
比如

var tempstrlist:tstringlist;//或者Tlist或者TIdCompressorZLibEx或者其他
begin
tempstrlist:=tstringlist.Create;
try
tempstrlist.Add('dd');
finally
//这里不free
end;
end;

这样做有什么后果吗?有人说delphi会自动处理释放的问题。
是这样的么?如果线程里面大量的tstringlist 不free 会导致系统崩溃么?

目前有一个问题:有一个测试的电脑在操作WebBrowser加载网页出现了程序异常,然后程序就没了。
我想问是不是和内存有关系呢?
...全文
329 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
7年 2012-06-11
  • 打赏
  • 举报
回复
webBrowser加载网页出现了程序异常,exe没了

在你自己的电脑上加载网页的代码设断点查看啊,跟踪下看看哪出问题,或者贴代码出来
一剑飘雪 2012-06-11
  • 打赏
  • 举报
回复
没人关注了么???
wanglipo 2012-06-08
  • 打赏
  • 举报
回复
顶起来,关注第二个问题,我也遇到过,用着突然程序就没有了,没有任何错误提示
一剑飘雪 2012-06-08
  • 打赏
  • 举报
回复
另外我说的 一个问题 程序突然没了 这个是什么情况呢?
出现了2次,都是同一个电脑,做同一个操作,就是用ebBrowser加载网页出现了程序异常,exe没了
一剑飘雪 2012-06-08
  • 打赏
  • 举报
回复
造成大量内存空置。那么这样的话,使用程序时间越长是不是电脑的cpu 越高?
也就是如何验证电脑内存空置???
oloveuxyz 2012-06-08
  • 打赏
  • 举报
回复
这个毫无疑问的!肯定要释放滴!
一剑飘雪 2012-06-08
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

继承自TComponent的VCL对象,在创建时如果指定一个有效的Owner,可以不考虑手工释放,Owner会负责。但是规范一点,本着谁创建谁释放的原则,我觉得手工添加Free的代码比较好。

至于TStringList,它并不是从TComponent继承的,构造函数中也没有类似TComponet那样指定OWner,所以,TStringList在创建以后需要手工释放。我记的有某大牛曾说,就算……
[/Quote]
原来delphi 对继承自TComponent的VCL对象 会负责自动释放的,不是对所以的对象。
之前误解了我
一剑飘雪 2012-06-08
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

不释放,内存泄漏。严重的,进程崩溃。
[/Quote]
进程崩溃 会导致电脑什么现象呢?卡死?程序突然没了?
lyhoo163 2012-06-08
  • 打赏
  • 举报
回复
造成大量内存空置。
cqs6616 2012-06-07
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

继承自TComponent的VCL对象,在创建时如果指定一个有效的Owner,可以不考虑手工释放,Owner会负责。但是规范一点,本着谁创建谁释放的原则,我觉得手工添加Free的代码比较好。

至于TStringList,它并不是从TComponent继承的,构造函数中也没有类似TComponet那样指定OWner,所以,TStringList在创建以后需要手工释放。我记的有某大牛曾说,就算……
[/Quote]

也学到一点新东西
liangpei2008 2012-06-07
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

我在4楼的回复中有一处小笔误,"类似TComponet那样指定OWner" 应改为"类似TComponent那样指定OWner",特此更正。

Delphi版藏龙卧虎,来不得半点马虎。
[/Quote]
哈哈,妖哥很幽默:)
山东蓝鸟贵薪 2012-06-07
  • 打赏
  • 举报
回复
[Quote=引用楼主 的回复:]
比如

Delphi(Pascal) code

var tempstrlist:tstringlist;//或者Tlist或者TIdCompressorZLibEx或者其他
begin
tempstrlist:=tstringlist.Create;
try
tempstrlist.Add('dd');
finally
//这里不f……
[/Quote]

这里不free的话,你也可在以CLOSE事件中FREE也是可以的

ccrun.com 2012-06-07
  • 打赏
  • 举报
回复
我在4楼的回复中有一处小笔误,"类似TComponet那样指定OWner" 应改为"类似TComponent那样指定OWner",特此更正。

Delphi版藏龙卧虎,来不得半点马虎。
ccrun.com 2012-06-07
  • 打赏
  • 举报
回复
继承自TComponent的VCL对象,在创建时如果指定一个有效的Owner,可以不考虑手工释放,Owner会负责。但是规范一点,本着谁创建谁释放的原则,我觉得手工添加Free的代码比较好。

至于TStringList,它并不是从TComponent继承的,构造函数中也没有类似TComponet那样指定OWner,所以,TStringList在创建以后需要手工释放。我记的有某大牛曾说,就算内存泄露也没关系,进程结束时系统就回收内存了,这样是极不负责任的。
s11ss 2012-06-07
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]
你这里的代码要free掉,不free的话,会造成内存泄漏,严重的会系统崩溃

因为Create后已经分配了内存空间,若不释放,系统会认为你一直在使用它,也就不会再分配这个地址空间给别的程序,这就造成了内存泄漏
当然现在的计算机内存都很大,不释放暂时没啥影响
但随着Create次数越来越多,内存泄漏也越积越多,最终是会用完的,系统崩溃只是时间上的问题
[/Quote]学习
kaikai_kk 2012-06-07
  • 打赏
  • 举报
回复
你这里的代码要free掉,不free的话,会造成内存泄漏,严重的会系统崩溃

因为Create后已经分配了内存空间,若不释放,系统会认为你一直在使用它,也就不会再分配这个地址空间给别的程序,这就造成了内存泄漏
当然现在的计算机内存都很大,不释放暂时没啥影响
但随着Create次数越来越多,内存泄漏也越积越多,最终是会用完的,系统崩溃只是时间上的问题
金卯刀 2012-06-07
  • 打赏
  • 举报
回复
不释放,内存泄漏。严重的,进程崩溃。
一、临界区 所谓临界区,就是一次只能由一个线程来执行的一段代码。如果把初始化数组的代码放在临界区内,另一个线程在第一个线程处理完之前是不会被执行的。 使用临界区的步骤: 1、先声明一个全局变量类型为TRTLCriticalSection; 2、在线程Create()前调用InitializeCriticalSection()过程来初始化,该函数定义是: void WINAPI InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 类型lpCriticalSection即是Delphi封装的TRTLCriticalSection。 3、在线程的需要放入临界区的代码前面使用EnterCriticalSection(lpCriticalSection)过程来开始建立临界区。在代码完成后用LeaveCriticalSection(lpCriticalSection)来标志临界区的结束。 4、在线程执行完后用DeleteCriticalSection(lpCriticalSection)来清除临界区。这个清除过程必须放在线程执行完后的地方,比如FormDesroy事件中。上面的例子中,若把该过程放在TMyThread.Create(False);后,会产生错误。 二、互斥: 互斥非常类似于临界区,除了两个关键的区别:首先,互斥可用于跨进程的线程同步。其次,互斥能被赋予一个字符串名字,并且通过引用此名字创建现有互斥对象的附加句柄。 提示临界区与事件对象(比如互斥对象)的最大的区别是在性能上。临界区在没有线程冲突时,要用10~15个时间片,而事件对象由于涉及到系统内核要用400~600个时间片。 使用互斥的步骤: 1、声明一个类型为Thandle或Hwnd的全局变量,其实都是Cardinal类型。Hwnd是handle of window,主要用于窗口句柄;而Thandle则没有限制。 2、线程Create()前用CreateMutex()来创建一个互斥量。该函数定义为: HANDLE WINAPI CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName:Pchar); LPSECURITY_ATTRIBUTES参数为一个指向TSecurityAttributtes记录的指针。此参数设为nil,表示访问控制列表默认的安全属性。 bInitalOwner参数表示创建互斥对象的线程是否要成为此互斥对象的拥有者。当此参数为False时,表示互斥对象没有拥有者。 lpName参数指定互斥对象的名称。设为nil表示无命名,如果参数不是设为nil,函数会搜索是否有同名的互斥对象存在。如果有,函数就会返回同名互斥对象的句柄。否则,就新创建一个互斥对象并返回其句柄。 返回值是一handle。当错误发生时,返回null,此时用GetLastError函数可查看错误的信息。 利用CreateMutex()可以防止程序多个实例运行,如下例: Program ABC; Uses Forms,Windows,…; {$R *.res} Var hMutex:Hwnd; Begin Application.Initialize; hMutex:=CreateMutex(nil,False,Pchar(Application.Title)); if GetLastErrorERROR_ALREADY_EXISTS then begin //项目要运行的咚咚 end; ReleaseMutex(hMutex); Application.Run; End; 在本节的例程中,我们只是要防止线程进入同步代码区域中,所以lpName参数设置为nil。 3、在同步代码前用WaitForSingleObject()函数。该函数使得线程取得互斥对象(同步代码)的拥有权。该函数定义为: DWORD WINAPI WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds); 这个函数可以使当前线程在dwMilliseconds指定的时间内睡眠,直到hHandle参数指定的对象进入发信号状态为止。一个互斥对象不再被线程拥有时,它就进入发信号状态。当一个进程要终止时,它就进入发信号状态。dwMilliseconds参数可以设为0,这意味着只检查hHandle参数指定的对象是否处于发信号状态,而后立即返回。dwMilliseconds参数设为INFINITE,表示如果信号不出现将一直等下去。 这个函数的返回值含义: WAIT_ABANDONED 指定的对象是互斥对象,并且拥有这个互斥对象的线程在没有释放此对象之前就已终止。此时就称互斥对象被抛弃。这种情况下,这个互斥对象归当前线程所有,并把它设为非发信号状态 WAIT_OBJECT_0 指定的对象处于发信号状态 WAIT_TIMEOUT 等待的时间已过,对象仍然是非发信号状态 再次声明,当一个互斥对象不再被一个线程所拥有,它就处于发信号状态。此时首先调用WaitForSingleObject()函数的线程就成为该互斥对象的拥有者,此互斥对象设为不发信号状态。当线程调用ReleaseMutex()函数并传递一个互斥对象的句柄作为参数时,这种拥有关系就被解除,互斥对象重新进入发信号状态。 注意除WaitForSingleObject()函数外,你还可以使用WaitForMultipleObject()和MsgWaitForMultipleObject()函数,它们可以等待几个对象变为发信号状态。这两个函数的详细情况请看Win32 API联机文档。 4、在同步代码结束后,使用ReleaseMutex(THandle)函数来标志。该函数只是释放互斥对象和线程的拥有者关系,并不释放互斥对象的句柄。 5、调用CloseHandle(THandle)来关闭互斥对象。请注意例程中该函数的使用位置。 三、还有一种用信号量对象来管理线程同步的,它是在互斥的基础上建立的,但信号量增加了资源计数的功能,预定数目的线程允许同时进入要同步的代码。有点复杂,想不到在哪可以用,现在就不研究论了。 unit Tst_Thread3U; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; Button2: TButton; Button3: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private procedure ThreadsDone(Sender: TObject); end; TMyThread=class(TThread) protected procedure Execute;override; end; var Form1: TForm1; implementation {$R *.dfm} const MaxSize=128; var NextNumber:Integer=0; DoneFlags:Integer=0; GlobalArry:array[1..MaxSize] of Integer; Lock:byte; //1-不同步 2-临界区 3-互斥 CS:TRTLCriticalSection; //临界区 hMutex:THandle; //互斥 function GetNextNumber:Integer; begin Result:=NextNumber; inc(NextNumber); end; procedure TMyThread.Execute; var i:Integer; begin FreeOnTerminate:=True; //终止后自动free OnTerminate:=Form1.ThreadsDone; if Lock3 then //非互斥情况 begin if Lock=2 then EnterCriticalSection(CS); //建立临界区 for i := 1 to MaxSize do begin GlobalArry[i]:=GetNextNumber; Sleep(5); end; if Lock=2 then LeaveCriticalSection(CS);//离开临界区 end else //-------互斥 begin if WaitForSingleObject(hMutex,INFINITE)=WAIT_OBJECT_0 then begin for i := 1 to MaxSize do begin GlobalArry[i]:=GetNextNumber; Sleep(5); end; end; ReleaseMutex(hMutex); //释放 end; end; procedure TForm1.ThreadsDone(Sender: TObject); var i:Integer; begin Inc(DoneFlags); if DoneFlags=2 then begin for i := 1 to MaxSize do Memo1.Lines.Add(inttostr(GlobalArry[i])); if Lock=2 then DeleteCriticalSection(CS); //删除临界区 If Lock=3 then CloseHandle(hMutex); //关闭互斥 end; end; //非同步 procedure TForm1.Button1Click(Sender: TObject); begin Lock:=1; TMyThread.Create(False); TMyThread.Create(False); end; //临界区 procedure TForm1.Button2Click(Sender: TObject); begin Lock:=2; InitializeCriticalSection(CS); //初始化临界区 TMyThread.Create(False); TMyThread.Create(False); end; //互斥 procedure TForm1.Button3Click(Sender: TObject); begin Lock:=3; // 互斥 hMutex:=CreateMutex(0,False,nil); TMyThread.Create(False); TMyThread.Create(False); end; end.
前段时间烈火下载给大家提供了一款Flash文件转EXE的Delphi源代码,我们知道SWF转EXE是很常见的,那么反相转换(EXE转Flash)你有没有见过呢?今天就带给大家这样的源程序。SWF就Flash的一种生成格式,依靠自已公司的FlashPlyaer插件运行,如果要想脱离插件,需导出成EXE文件格式,用Flash软件可以,如果没有可以自己写程序将SWF转换成EXE,将EXE转换成SWF是个逆过程,具体请看代码。   // 将Edit1中的路径赋给exeFileName变量   exeFileName := Edit1.Text;   // 修改EXE路径中的扩展名,以获取SWF文件的存储路径。   swfFileName := ChangeFileExt(exeFileName, ‘.swf‘);   // 检查指定的EXE文件是否存在,如果不存在则退出过程,不做任何处理。   if not FileExists(exeFileName) then   begin     ShowMessage(‘文件未找到.);     Exit;   end;   // 分别创建swfFile及exeFile对象   // 创建空的swf文件并赋于写入的权限(fmOpenWrite)   swfFile:=TFileStream.Create(swfFileName, fmCreate or fmOpenWrite);   // 打开EXE文件,并赋于读取的权限(fmOpenRead)   exeFile:=TFileStream.Create(exeFileName, fmOpenRead);   // 从EXE文件开头搜索   // 将文件指针移到存储SWF文件大小的地方   // exeFile.Size用于获取整个EXE文件的大小,减去4个字节正好是SWF文件大小储存的地方   exeFile.Seek(exeFile.Size - 4, soFromBeginning);   // 读出SWF文件的大小   exeFile.Read(nFileSize, 4);   // 将文件指针移动到SWF文件开始处   exeFile.Seek(exeFile.Size - (nFileSize   8), soFromBeginning);   // 将SWF文件所有内容复制到swfFile对象中去   // 此时SWf文件内容已保存在硬盘中了   swfFile.CopyFrom(exeFile, nFileSize);   // 释放资源   swfFile.Free;   exeFile.Free;   ShowMessage(‘SWF文件已成功还原.); end;

5,392

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧