线程 带参数 吃内存?高手帮忙看看 ( 积分: 200 )

  • 主题发起人 主题发起人 天真男孩
  • 开始时间 开始时间

天真男孩

Unregistered / Unconfirmed
GUEST, unregistred user!
每运行一下,内存就增加一次?
该怎么写来释放?
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
PData=^TData;
TData=record
ip:string;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function MyThreadping(Ptr:Pointer):integer;stdcall;
var
ls_ip:string;
Data:PData;
begin
Data:=PData(Ptr);
ls_ip:=Data^.ip;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ThreadID:DWord;
Data:PData;
i:integer;
begin
for i:=1 to 1000do
begin
New(Data);
Data^.ip:=inttostr(i);
CreateThread(nil,0,@MyThreadping,Data,0,ThreadID);
//dispose(Data);
这上这句就报内存出错
end;
end;
end.
 
你传的是指针
在你释放内存后线程使用指针访问这个对象的时候该对象已经被你释放了当然错了
如果只是为了传值就不要使用指针
如果使用指针就等线程释放后再释放指针指向的内存
 
如果光传值,该怎么改?谢谢啦
 
begin
CreateThread(nil,0,Pointer(123),0,ThreadID);
//把 123 传进去
end;

function MyThreadping(Ptr:Pointer):integer;stdcall;
var
aa: dword;
begin
aa:= dword(ptr);
end;
 
本质上跟你写程序的思路有关,而不是跟传不传的是指针有关
for i:=1 to 1000do
begin
New(Data);
Data^.ip:=inttostr(i);
CreateThread(nil,0,@MyThreadping,Data,0,ThreadID);
Sleep(5);
dispose(Data);
// 这上这句就报内存出错
end;

你加上sleep(5)那一句,表示我主线程放弃执行的机会而让辅助线程来完成,它完成了你再dispose,否则的话你在你的时间片里dipose都做完了,而MyThreadping可能还没开始执行,所以MyThreadping执行时你的那块内存已经被dispose掉了
而且,就算你写正确的你的程序还是会有内存泄露
PData=^TData;
TData=record
ip:string;
//这儿不能声明成string型,应该声明成shortstring
end;
 
string 也没有问题的,在 Execute最后 Dispose掉就没事了。
 
string 也没有问题的,在 Execute最后 Dispose掉就没事了。!!!!
你可以找CnMemProf.pas单元调试一下就知道是没有问题了,当你使用结构指针时
这样做一定会造成泄露
 
to 52free:
是什么版本的Delphi? 我用 D7 UPD1 + RTL 补丁,似乎没发生这个现象?
 
改为全局变量,程序退出时在释放!或下次调用前释放!
 
随便什么版本
 
这跟版本没什么关系,给你贴个分析看看
于释放Pointer指针引起的内存泄漏
无论是用Delphi还是VC编写的程序,内存泄漏始终是一个令每个程序员头痛的问题,特别是一个大型的服务器系统,内存泄漏更会对系统的长期稳定运行造成致命的硬伤,往往系统是很正常的运行几天后才出现问题。而内存泄漏也是一个极难以发现的BUG。笔者在Delphi中开发一个数采服务器时就出现过这种情况,当数采服务器运行时,从Win2000的“任务管理器”中能明显看出该进程所占内存在不断的增大,直致该进行崩溃。笔者花了很长的时间才发现了问题所在,原来是由于笔者直接对结构体的Pointer指针进行释放操作引出的内存泄漏。为此作者将问题分析如下,以免诸位再步我后尘。
以下为该内存泄漏的重现代码,为了说明问题,笔者删除了无关代码行:
PDataItem =^TDataItem;
TDataItem = Record
.
.
.
strData: String;
end;

lstDataItems: TList;
pItem: PDataItem;
lstDataItems := TList.Create;
new(pItem);
// 分配了一个结构体的内存
lstDataIetms.Add(pItem);
// 存入列表中
.
. // 自己的事务处理代码
.
// 然后函数结束时释放分配的内存
for i := 0 to lstDataItems.Count-1do
Dispose(lstDataItems.Items);
你能看出问题所在吗?对了,Dispose(lstDataItems.Items) 语句会引起内存泄漏,lstDataItems.Items返回的是一个Pointer类型的数据,Dispose函数对Pointer类型数据释放内存时,只会释放该指针所指向的内存块。如上代码所示,Pointer指向的是一个结构体TDataItem,那么,该结构体所本身所占的内存块就被释放了,但是,如果该结构体内部的数据成员如果为String类型、PChar、或对象时,这些数据成员自身所占用的内存会得不到释放,从而引起内存泄漏。显而易见,以上代码至少会引strData数据成员的内部内存泄漏。
从上例可见,在释放一个指针的内存时,为Dispose函数传递一个明确的数据类型是必要的,而为了贪图方便直接传递Pointer指针,有可能会出现内存泄漏,上例正确的代码应该这样的:
// 然后函数结束时释放分配的内存
for i := 0 to lstDataItems.Count-1do
begin
pItem := lstDataItems.Items;
Dispose(pItem);
end;

当然,如果结构体中包含有PChar类型、结构体指针或其类似的数据成员,则你必须在释放该结构指针之前保证这些成员的私有内存得到合理释放,或在其他地方能够能到合理释放,否则也会引起内存泄漏。
 
原来说这个,不按类型来 Dispose 肯定出问题了,这个不是 Delphi 的错。
 
52free说的很对
我以前在写C++代码时也遇到同样的问题
先释放结构里的指针的内存,再释放该结构,就不会有内存泄漏了
 
string的话本来就是有生存期管理的,无法手动释放。
 
begin
CreateThread(nil,0,Pointer(123),0,ThreadID);
//把 123 传进去
end;

function MyThreadping(Ptr:Pointer):integer;stdcall;
var
aa: dword;
begin
aa:= dword(ptr);
end;
这个办法 好像内存也是越来越多的,不会释放的
 
我想写个ping的多线程,线程里要传IP地址,内存要释放,该怎么改?
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
PData=^TData;
TData=record
ip:string;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function MyThreadping(Ptr:Pointer):integer;stdcall;
var
ls_ip:string;
Data:PData;
begin
Data:=PData(Ptr);
ls_ip:=Data^.ip;
....(这里省了ping的过程,现成的有。)
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ThreadID:DWord;
Data:PData;
i:integer;
begin
for i:=1 to 254do
begin
New(Data);
Data^.ip:='192.168.0.'+inttostr(i);
CreateThread(nil,0,@MyThreadping,Data,0,ThreadID);
//dispose(Data);
这上这句就报内存出错
end;
end;
end.
 
function MyThreadping(Ptr:Pointer):integer;stdcall;
var
ls_ip:string;
Data:PData;
begin
Data:=PData(Ptr);
ls_ip:=Data^.ip;
....(这里省了ping的过程,现成的有。)
dispose(Data);
//那一句释放的放到这里,而且你的结构的string类型要改成shortstring
end;
 
再说一句看来授人以渔还不如授人以鱼来得好啊
 
后退
顶部