关于内存漏洞的问题?请高手大哥们帮帮小弟~ ( 积分: 200 )

  • 主题发起人 主题发起人 asksomeone
  • 开始时间 开始时间
A

asksomeone

Unregistered / Unconfirmed
GUEST, unregistred user!
做了一个多线程读数据库的小软件,可是当软件启动四五个小时总会死掉,界面不死,就是读不出来东西了,后用软件查得如下数据,小弟真不知道从何下手,请高手大哥们帮帮我,谢谢
可用地址空间 : 1024 KB(1048576 Byte)
未提交部分 : 912 KB(933888 Byte)
已提交部分 : 112 KB(114688 Byte)
空闲部分 : 109 KB(111616 Byte)
已分配部分 : 2 KB(2664 Byte)
全部小空闲内存块 : 8 KB(9056 Byte)
全部大空闲内存块 : 100 KB(102560 Byte)
其它未用内存块 : 0 KB(0 Byte)
内存管理器消耗 : 0 KB(408 Byte)
地址空间载入 : 0%
当前出现 19 处内存漏洞 :
0) 0000000000CE202C - 135($0087)字节 - 不是对象
1) 0000000000CE2600 - 35($0023)字节 - 不是对象
2) 0000000000CEFFBC - 15($000F)字节 - 不是对象
3) 0000000000D118EC - 71($0047)字节 - 不是对象
4) 0000000000D04C40 - 15($000F)字节 - 不是对象
5) 0000000000D11930 - 70($0046)字节 - 不是对象
6) 0000000000D05350 - 15($000F)字节 - 不是对象
7) 0000000000D11974 - 70($0046)字节 - 不是对象
8) 0000000000D069FC - 15($000F)字节 - 不是对象
9) 0000000000D119B8 - 70($0046)字节 - 不是对象
10) 0000000000D119FC - 70($0046)字节 - 不是对象
11) 0000000000D072CC - 15($000F)字节 - 不是对象
12) 0000000000D11A40 - 70($0046)字节 - 不是对象
13) 0000000000CE6410 - 15($000F)字节 - 不是对象
14) 0000000000D11A84 - 70($0046)字节 - 不是对象
15) 0000000000CE8A84 - 15($000F)字节 - 不是对象
16) 0000000000D11AC8 - 70($0046)字节 - 不是对象
17) 0000000000D01D74 - 35($0023)字节 - 不是对象
18) 0000000000CEB79C - 39($0027)字节 - 不是对象
 
只要系统不提示你内存不足,在任务管理器中查看内存占用并不十分突出的话,那么你的问题就不在于这简单的十来个内存泄露,而是线程或程序逻辑错误,程序停止工作了而已。
 
运行4-5个小时就这些泄露,应该不是导致问题的原因。
可能线程死掉了。
你在线程内加入日志记录,然后看看日志文件,到底发生了什么
 
to shangshang
谢谢您的回答,我的程序页面上还有一个Webbrowser显示一个网页,我试过了,死了后,连网页都打不开了
to ufo!
谢谢您的回答,日志文件该怎么做?
 
没人气了,我自己顶,唉
 
日志文件,就是你记录一个计数到一个文件而已.可以记录是什么线程 ,什么时间,当然计数是多少.让线程死掉后,看这个日志文件的内容就知道什么时间死的.
 
1) 0000000000A2CC74 - 35($0023)字节 - 不是对象 //注册表 if reg.Readstring('font')<>''
2) 0000000000A29014 - 31($001F)字节 - 不是对象 // if reg.Readstring('font')<>''
这里找到了这么多
 
网页都打不开,那应该是主线程死了吧,
你提供的信息没有用,不能判断你的程序故障出在哪里,反正应该不是内存泄露导致的程序故障。因为如果大量极速的内存泄露,会很明显的系统提示内存不足的。
至于上面我们的话的意思是让你好好分析调试一下你的程序代码,比如,写线程运行的日志(就是不停的在每个函数或关键点作一个输出,输出为文本或调试器信息都行)。这只是个方法问题了,除非你把源码全贴出来,要不,谁能知道你的问题在哪里呢。
 
0) 00000000009E202C - 135($0087)字节 - 不是对象
这个错竟然是
uses
midaslib;如果去掉就没事了,这个可怎么办啊
 
我用D7(D版)写了个最简单的程序,界面上只放一个ADOTable控制,然后用CHECKMEM函数检查内存泄漏问题,竟然提示有内存泄漏,请问各位有没有遇到过,是不是我的Delphi版本问题?
检查结果如下:
===== Project1.exe,2007-06-07 12:34:00 =====
可用地址空间 : 1024 KB(1048576 Byte)
未提交部分 : 1008 KB(1032192 Byte)
已提交部分 : 16 KB(16384 Byte)
空闲部分 : 13 KB(14052 Byte)
已分配部分 : 1 KB(2000 Byte)
全部小空闲内存块 : 0 KB(232 Byte)
全部大空闲内存块 : 13 KB(13820 Byte)
其它未用内存块 : 0 KB(0 Byte)
内存管理器消耗 : 0 KB(332 Byte)
地址空间载入 : 0%
当前出现 1 处内存漏洞 :
0) 0000000000E21FCC - 135($0087)字节 - 不是对象



回复人:nlight_yl(穆穆) ( ) 信誉:100 2007-6-7 14:09:12 得分:0


?
如果只是加一个ADOTable 并连接了一个表的话 我用BoundsChecker检查是没有泄漏问题 不知道你有没有做什么其他的操作


Top

回复人:martinxiao(里斯) ( ) 信誉:98 2007-6-7 15:20:49 得分:0


?
我没有做任何动作,也没连接数据库,只找开就关闭程序。
我也找BoundsChecker来测试一下看看
 
type
myTimer = class(TThread) {timer线程}
private
{ Private declarations }
protected
procedure timefun;
public
procedure Execute;
override;
constructor Create;
destructor Destroy;override;
end;

var
fresh:mytimer;
// timer线程

fresh:=mytimer.create;//只要有这一句就出现了内存漏洞,怎么办呢?
 
请好心人给我看一下吧,多谢
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ImgList, ExtCtrls,Registry,ActiveX, Grids;

type

myTimer = class(TThread)
private
{ Private declarations }
protected
procedure timefun;
public
procedure Execute;
override;
constructor Create;
destructor Destroy;override;
end;

TF_main = class(Tform)
Panel1: TPanel;
Panel4: TPanel;
SG: TStringGrid;
Edit1: TEdit;
ImageList1: TImageList;
Timer1: TTimer;
Button1: TButton;
procedure Timer1Timer(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
F_main: TF_main;
fresh:mytimer;
// timer线程
timecmd:string;
implementation
uses data;
{$R *.dfm}
procedure TF_main.Timer1Timer(Sender: TObject);
begin
fresh.Resume;
end;

procedure TF_main.FormShow(Sender: TObject);
begin
fresh:=mytimer.Create;
end;

constructor MyTimer.Create;
begin
inherited Create(true);//false构造的同时即唤醒,true为不唤醒
FreeOnTerminate := True;
end;

destructor MyTimer.Destroy;
begin
inherited;
end;

procedure mytimer.timefun;
var i:integer;
begin
CoInitialize(nil);
i:=0;
timecmd:='exec myxx ''111''';
//一个存储过程
fm_data.Cd_timer1.Close;
f_main.Edit1.text:=timecmd;
fm_data.Cd_timer1.CommandText:=timecmd;
try
fm_data.Cd_timer1.Open;
if (fm_data.cd_timer1.Active) and (fm_data.cd_timer1.RecordCount>0) then
begin
fm_data.Cd_timer1.first;
while i<=fm_data.cd_timer1.RecordCount-1 do
begin
f_main.sg.RowCount:=f_main.sg.RowCount+1;// 在sg(一个STRINGGRID)中显示数据
F_main.SG.Cells[0,f_main.sg.RowCount-1]:=fm_data.Cd_timer1.fieldbyname('Username').asstring;
f_main.SG.Cells[2,f_main.SG.RowCount-1]:=fm_data.Cd_timer1.fieldbyname('password').asstring;
f_main.sg.Cells[3,f_main.sg.RowCount-1]:=fm_data.cd_timer1.fieldbyname('netcall').asstring;
fm_data.cd_timer1.next;
i:=i+1;
end;
end;
except
fresh.Suspend;
end;
CoUninitialize;
end;
procedure MyTimer.Execute;
begin
While not Terminateddo
begin
try
timefun;
finally
fresh.suspend;
end;

end;
end;

end.
 
唉,看你那么执着,免得你走的过弯,再告诉你一些。delphi本身的确是存在内存泄露的,这个可以用任何一个检测单元或工具检测出来,这个不算影响你的程序。不要在这里耗时间了。
不过很遗憾,实在不想打击你,你的代码从风格,设计思路,实现问题太多,你还没明白线程和timer的区别搞明白,一个毫无意义的线程,一个奇怪的控制线程运行机制,糟糕的代码风格,唉。我建议你还是别用线程了。效果一样的。相信我就试试吧。
 
如果用线程。
线程中使用到的数据库组件都在线程内动态创建,
delphi中使用线程的大忌,别去直接访问vcl对象,比如form,grid等等。尤其是填充绘制类的操作,因为vcl不支持多线程。
在线程中提取后,用线程提供的同步函数来执行填充grid的过程,那个所谓的timer,根本豪无用处,你不如线程内用一个无限循环,然后最简单的用一个sleep来实现间隔。
 
to shangshang 多谢您的指教,我给您发了邮件,上面的我已改了一下,昨天太急了

请大哥们不吝赐教啊,这里的每一个人都是我的老师,您的一句话,可能让我受益终生
 
老天啊,帮帮我啦~欲哭无泪
 
type
TQueryThread=class(TThread)
private
FHandle:HWND;
FHasResult:Boolean;
FQuery:TAdoQuery;
procedure QueryExecute;
procedure QueryOpen;
protected
procedure Execute;override;
public
constructor Create(AHandle:HWND;
AdoQuery:TAdoQuery;
HasResult:Boolean);
end;

implementation
constructor TQueryThread.Create(AHandle:HWND;AdoQuery: TAdoQuery;
HasResult: Boolean);
begin
inherited Create(True);
FreeOnTerminate:=True;
FHandle:=AHandle;
FQuery:=AdoQuery;
FHasResult:=HasResult;
Resume;
end;

procedure TQueryThread.Execute;
begin
if FHasResult then
QueryOpen
else
QueryExecute;
end;

procedure TQueryThread.QueryExecute;
begin
try
FQuery.ExecSQL;
PostMessage(FHandle, WM_ThreadDone, Self.ThreadID,0);
except
on E:Exceptiondo
PostMessage(FHandle,WM_ThreadDone, Self.ThreadID,MaxInt);
end;
end;

procedure TQueryThread.QueryOpen;
begin
try
FQuery.Open;
PostMessage(FHandle, WM_ThreadDone, Self.ThreadID,0);
except
on E:Exceptiondo
PostMessage(FHandle,WM_ThreadDone, Self.ThreadID,MaxInt);
end;
end;

摘自(http://www.delphibbs.com/delphibbs/dispq.asp?lid=2140793)
这是以前的一个贴子上的方活,我的这种也可以用吗?
 
算了吧,就这样结了吧,不再占用大家的时间了
 
后退
顶部