内存泄漏,附源码,分数不多,求帮助
最近在写一套系统,用了ADO,想增加一些功能,改写ADOQuery控件,再系统调试时发现内存泄漏,烦请各位前辈帮忙修改。
控件完整源码如下:
unit ADOMacQuery;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Db, ADODB, DBTables;
type
TADOMacQuery = class(TADOQuery)
private
FKeyField: string;
FMacParams: TParams;
FMacSQL: TStrings;
procedure SetMacParams(Value: TParams);
procedure SetMacSQL(Value: TStrings);
procedure MacSQLChanged(Sender: TObject);
protected
procedure ExpandMacs; dynamic;
procedure OpenCursor(InfoQuery: Boolean); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function ParamByN(const Value: string): TParam;
procedure ExecSQL;
procedure ReQuery();
published
property SQL: Tstrings read FMacSQL write SetMacSQL;
property Parameters: TParams read FMacParams write SetMacParams;
property KeyField: string read FKeyField write FKeyField;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('SelfControl', [TADOMacQuery]);
end;
constructor TADOMacQuery.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FMacSQL := TStringList.Create;
TStringList(FMacSQL).OnChange := MacSQLChanged;
FMacParams := TParams.Create(self);
ParamCheck := False;
end;
destructor TADOMacQuery.Destroy;
begin
FreeAndNil(FMacSQL);
FreeAndNil(FMacParams);
inherited Destroy;
//FMacParams.Free;
end;
procedure TADOMacQuery.SetMacParams(Value: TParams);
begin
FMacParams.AssignValues(Value);
end;
function TADOMacQuery.ParamByN(const Value: string): TParam;
begin
Result := FMacParams.ParamByName(Value);
end;
procedure TADOMacQuery.SetMacSQL(Value: TStrings);
begin
if FMacSQL.Text = Value.Text then
Exit;
// Disconnect;
FMacSQL.BeginUpdate;
try
FMacSQL.Assign(Value);
finally
FMacSQL.EndUpdate;
end;
end;
procedure TADOMacQuery.MacSQLChanged(Sender: TObject);
var
List: TParams;
i: integer;
begin
if (csReading in ComponentState) then
Exit;
List := TParams.Create(Self);
try
{FText :=}List.ParseSQL(FMacSQL.Text, True);
List.AssignValues(FMacParams);
for i := List.Count - 1 downto 0 do
if List[i].DataType = ftUnknown then
begin
List[i].DataType := ftString;
List[i].AsString := '';
end;
FMacParams.Clear;
FMacParams.Assign(List);
finally
List.Free;
end;
end;
procedure TADOMacQuery.OpenCursor(InfoQuery: Boolean);
begin
ExpandMacs;
inherited OpenCursor(InfoQuery);{{*************地址指向这里***************}}
end;
procedure TADOMacQuery.ExecSQL;
begin
ExpandMacs;
inherited ExecSQL;
end;
procedure TADOMacQuery.ExpandMacs;
var
i: integer;
tsSQL, tsValue: string;
begin
tsSQL := FMacSQL.GetText(); {*************地址指向这里***************}
for i := FMacParams.Count - 1 downto 0 do
begin
case FMacParams[i].DataType of
ftDate: tsValue := '''' + FormatDatetime('yyyy-mm-dd',
FMacParams[i].AsDate) + '''';
else
tsValue := FMacParams[i].AsString;
end;
tsSQL := StringReplace(tsSQL, ':' + FMacParams[i].Name
, tsValue, [rfReplaceAll, rfIgnoreCase]);
end;
inherited SQL.SetText(PChar(tsSQL));
end;
procedure TADOMacQuery.ReQuery();
var
SavePlace: TBookMark;
KeyValue: Variant;
begin
//浏览窗口刷新数据,并恢复记录指针
SavePlace := nil;
DisableControls;
try
if FKeyField = 'RecNo' then
begin
if not IsEmpty then
SavePlace := GetBookmark;
end
else if FKeyField <> '' then
KeyValue := FieldByName(FKeyField).Value;
Close;
Open;
if FKeyField = 'RecNo' then
begin
if SavePlace <> nil then
begin
try
if BookmarkValid(SavePlace) then
GotoBookmark(SavePlace);
finally
FreeBookmark(SavePlace);
end;
end;
end
else if FKeyField <> '' then
Locate(FKeyField, KeyValue, []);
finally
EnableControls;
end;
end;
end.
泄漏情况:
一个内存块已泄露. 大小是: 36
该内存块分配于线程 0x1714, 当时的堆栈跟踪(返回地址):
402E4C
40E45D
40E499
423AF9
4C3FE3
4C3FAE
48E407
48E252
4C43BB
44AD0A
44108D
该内存块当前被用于一个属于以下类的对象: 未知