动态创建的控件释放的问题? ( 积分: 200 )

  • 主题发起人 主题发起人 eastweast
  • 开始时间 开始时间
E

eastweast

Unregistered / Unconfirmed
GUEST, unregistred user!
有一个公共的Unit.里面有一个类似下面的函数:
function test(abc:string):TQuery;
var
myQuery:TAdoQuery;
begin
myQuery:=TAdoQuery.Create(nil);
myQuery.sql:='select * from aaa';
myQuery.open;
Result:=myQuery;
end;
另一窗体uses了此公共单元,并且使用类似以下代码:
AdoQuery1:=test('123');
请教一下,function test中创建的myQuery在何时会被free掉,上面的代码,会不会造成内存泄漏?如果会,代码该如何写?
 
每次调用这个函数都是 Create 一个 TAdoQuery,多处调用就会产生多个 TAdoQuery
所以调用这函数的地方需要自己 Free 掉 TAdoQuery
只要注意每个调用这个函数的地方都 Free 了,就不会出现内存泄漏
不过这种方式返回 TAdoQuery 确实不太好
 
不知道你ADOQuery1是不是拖下来的控件,实际上你的Test函数已经创建了一个对象,但是却没有释放(Free)所以如果有类似
var
adq: tadoquery;
begin
adq:= tadoquery.create(nil);
...
adq:= Test('123');
...
end;
这样的语句是有危险的,你应该用一个没有创建的对象去接这个函数的返回值,并且保证使用完成后释放该对象
 
说明:
公共单元的函数就是要返回一个sql的数据集,然后再由他form的控件去接此返回值,然后再显示或者产生报表等。
比如:其它form地方可能会用:datasource1.datasouce:=test('abc')的方式,然后通过dbgrid显示数据。
如果要释放,释放的代码该如何写?感觉好像代码确实有问题,但是该如何改善呢?或者要实现类似的功能,该如何作?
 
感觉你这个思维方式就不好!
你用函数返回一个 TAdoQuery 就不是一个好办法。如果你这样做,当你多处调用TADOQuery的时候,可能产生意想不到的后果。
我觉得:
1、你随时用ADOQuery随时动态创建不用的时候可以FREE掉;
2、你可以用其他的变量返回数据用于取代数据集,
给你一个建议:
=======================================
procedure test(abc:string):TStringList;
var
myQuery:TAdoQuery;
begin
result:=TStringList.create;
myQuery:=TAdoQuery.Create(nil);//nil这里比用self要好!
try
....
myQuery.close;
myQuery.sql.clrae;
myQuery.sql:='select * from abc';
myQuery.open;
Result.add(qry.fields[1].asstring);
finally
qry.free;
end;
end;
 
同意listhano说法,不过我建议你还是随时动态创建,随时释放掉就是最好的办法了,
为什么要写一个函数呢?而且这种函数根本就没有什么意义,
调用还麻烦,容易出问题,写函数是为了解决问题的,
你这个函数是制造问题了,呵呵。
 
谢谢哦。我代码改改试看看。
各位有什么见解,还请多多指点。
 
你这样做不好,其实你可以直接将query传进去。
function aa(Q:TADOQuery):boolean
begin
end;
 
采用楼上建议,将返回值放到参数里面,可是也只能用tadoquery来接,不能使用比如datasource.dataset来接?????[:(]
 
创建AdoQuery后datasource.dataset := AdoQuery
不过你的写发有问题,动态创建AdoQuery并且显示查询结果,不应该你这么写!
 
可是该如何写呢?因为adoquery并不是返回的,而是在参数里面的。不想再去定义一个TAdoQuery来做。
多了,我记得有一种参数可以是out的,是否可以这么用?又该如何写呢?
 
function aa(const Q:TADOQuery):boolean
begin
end;
所有的对象传递,传的都是指针,你在函数里面做完查询,查询的结果就在q里面了。
 
真是很晕.,你 有没有试过我的代码?
那样写,数据就已经直接给你了.
 
aerobull,试过了你的代码,但是报告错误。也许是你自己没有试过吧
我明白你的意思,我也是这么想的,我修改一下代码试试。
 
FUNCTION Record2Ts(CONST ASql: STRING
VAR ts: tstrings): boolean;
VAR
i : integer;
BEGIN
WITH dm.OraQuery DO
TRY
sql.Text := Asql;
open;
FOR i := 0 TO FieldCount - 1 DO
ts.Values[Fieldlist.Fields.FieldName] :=
Fieldlist.Fields.AsString;
close;
result := true;
EXCEPT
result := false;
END;
END;
直接把SQL转化成LIST,形式如
XM=张三
XB=男
CSSJ=2007-01-01
不过不能用BLOB字段类型。
 
你这样做不好,其实你可以直接将query传进去。
function aa(Q:TADOQuery):boolean
begin
end


正解
 
我当然试过了的:)
你试试这个:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Grids, DBGrids, DB, ADODB;

type
TForm1 = class(TForm)
Button1: TButton;
DataSource1: TDataSource;
ADOQuery1: TADOQuery;
DBGrid1: TDBGrid;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

function test(Q:TADOQuery):boolean;
begin
Q.Close;
Q.SQL.Text:='Select * from employees';
Q.Open;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
test(ADOQuery1);
end;

end.


=========
object Form1: TForm1
Left = 192
Top = 103
Width = 696
Height = 480
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 176
Top = 344
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object DBGrid1: TDBGrid
Left = 104
Top = 112
Width = 465
Height = 225
DataSource = DataSource1
TabOrder = 1
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
end
object DataSource1: TDataSource
DataSet = ADOQuery1
Left = 272
Top = 128
end
object ADOQuery1: TADOQuery
ConnectionString =
'Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security In' +
'fo=False;Initial Catalog=Northwind'
Parameters = <>
Left = 208
Top = 120
end
end
 
aerobull,你没有明白我的意思,我知道你试过了,你是有放一个adoquery控件到form上面,而我是没有的。我只有一个datasouce跟一个dbgrid而已。
其实我的意思是想把那个结果直接给datasource的dataset,而不是再通过一个query.
 
那就在create里代码建立这个query,close窗体后释放这个query就行了,代码关连其它控件
 
你如果只有一个datasouce跟一个dbgrid而已
那么你一定要按boy2002cn说的,create,关闭时free掉它,不然用你自己发的那个是有内存泄漏的.
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部