delphi在释放对象时丢失值
对不起,如果我的问题也一样 在Delphi中,我生成如下函数:delphi在释放对象时丢失值,delphi,delphi-xe2,Delphi,Delphi Xe2,对不起,如果我的问题也一样 在Delphi中,我生成如下函数: function TModuleDatabase.LoadCountryList():TDictionary<integer, String>; var UQ: TUniQuery; UC: TUniConnection; CountryList: TDictionary<integer, String>; begin CountryList := TDictionary<integer
function TModuleDatabase.LoadCountryList():TDictionary<integer, String>;
var
UQ: TUniQuery;
UC: TUniConnection;
CountryList: TDictionary<integer, String>;
begin
CountryList := TDictionary<integer, String>.Create;
UC := UniConnection2;
UQ := TUniQuery.Create(nil);
try
UQ.Connection := UC;
try
UQ.SQL.Clear;
UQ.SQL.Add('SELECT ID,NAME FROM COUNTRY ORDER BY NAME ASC');
UQ.Open;
while not UQ.Eof do
begin
CountryList.Add(UQ.Fields.FieldByName('ID').AsInteger,UQ.Fields.FieldByName('NAME').AsString);
UQ.Next;
end;
Result := CountryList;
except
on E:Exception do
ModuleMsgDialog.WarningMsg(E.Message);
end;
finally
UQ.Close;
UQ.Free;
CountryList.Free;
end;
end;
function CreateAndPopulateCountryDict: TDictionary<Integer, string>;
begin
Result := TDictionary<Integer, string>.Create;
try
// populate Result here
except
Result.Free; // until this function returns, we are responsible for lifetime
raise;
end;
end;
var
Countries: TDictionary<Integer, string>
....
Countries := CreateAndPopulateCountryDict;
try
// do stuff with Countries
finally
Countries.Free;
end;
函数TModuleDatabase.LoadCountryList():t字典;
变量
UQ:TUniQuery;
UC:连接;
国家列表:t词典;
开始
CountryList:=TDictionary.Create;
UC:=单连接2;
UQ:=TUniQuery.Create(nil);
尝试
UQ.连接:=UC;
尝试
UQ.SQL.Clear;
Add('SELECT ID,NAME FROM COUNTRY ORDER BY NAME ASC');
开放式;
而不是UQ.Eof do
开始
CountryList.Add(UQ.Fields.FieldByName('ID').AsInteger,UQ.Fields.FieldByName('NAME').AsString);
UQ.Next;
结束;
结果:=国家列表;
除了
关于E:Exception-do
ModuleMsgDialog.WarningMsg(E.Message);
结束;
最后
UQ.关闭;
UQ.免费;
国家名单。免费;
结束;
结束;
我将该函数与其他DataModule分开,以避免每次在每个表单中重复此函数。但当我从一个表单中调用这个函数时:
procedure TCompanyDetailsForm.FormCreate(Sender: TObject);
var
i: Integer;
sItem: String;
CountryList: TDictionary<integer, String>;
begin
PageControl1.ActivePage := AddressTab;
CountryList := ModuleDatabase.LoadCountryList();
for i in CountryList.Keys do
begin
LocationCbbx.Items.AddObject(CountryList.Items[i],TObject(i));
end;
end;
过程tcompanydailsform.FormCreate(发送方:TObject);
变量
i:整数;
sItem:字符串;
国家列表:t词典;
开始
PageControl1.ActivePage:=地址选项卡;
CountryList:=ModuleDatabase.LoadCountryList();
因为我在CountryList中。按键可以
开始
LocationCbbx.Items.AddObject(CountryList.Items[i],TObject(i));
结束;
结束;
问题出在CountryList.Free。字典中的所有项在使用前已释放。
如果我不释放内存,就会导致内存泄漏
如何在做免费之前传输数据的最佳方式。或者如何在调用后以其他形式或单位释放值
谢谢您的帮助。您有两个主要选择 选项1–调用方提供实例化对象 在这里,您让来电者承担终身责任。调用者传入一个实例化的对象,被调用者填充它
procedure PopulateCountryDict(Countries: TDictionary<Integer, string>);
begin
// populate Countries here
end;
procedure PopulateCountryDict(国家/地区:t词典);
开始
//在这里居住的国家
结束;
选项2–调用者返回一个新实例化的对象,该对象也被填充
这是可行的,但是一旦被调用方返回,调用方必须承担整个生命周期的责任。看起来是这样的:
function TModuleDatabase.LoadCountryList():TDictionary<integer, String>;
var
UQ: TUniQuery;
UC: TUniConnection;
CountryList: TDictionary<integer, String>;
begin
CountryList := TDictionary<integer, String>.Create;
UC := UniConnection2;
UQ := TUniQuery.Create(nil);
try
UQ.Connection := UC;
try
UQ.SQL.Clear;
UQ.SQL.Add('SELECT ID,NAME FROM COUNTRY ORDER BY NAME ASC');
UQ.Open;
while not UQ.Eof do
begin
CountryList.Add(UQ.Fields.FieldByName('ID').AsInteger,UQ.Fields.FieldByName('NAME').AsString);
UQ.Next;
end;
Result := CountryList;
except
on E:Exception do
ModuleMsgDialog.WarningMsg(E.Message);
end;
finally
UQ.Close;
UQ.Free;
CountryList.Free;
end;
end;
function CreateAndPopulateCountryDict: TDictionary<Integer, string>;
begin
Result := TDictionary<Integer, string>.Create;
try
// populate Result here
except
Result.Free; // until this function returns, we are responsible for lifetime
raise;
end;
end;
var
Countries: TDictionary<Integer, string>
....
Countries := CreateAndPopulateCountryDict;
try
// do stuff with Countries
finally
Countries.Free;
end;
函数CreateAndPopulateCountryDict:TDictionary;
开始
结果:=t字典。创建;
尝试
//在此处填充结果
除了
Result.Free;//在该函数返回之前,我们负责整个生命周期
提高;
结束;
结束;
调用代码如下所示:
function TModuleDatabase.LoadCountryList():TDictionary<integer, String>;
var
UQ: TUniQuery;
UC: TUniConnection;
CountryList: TDictionary<integer, String>;
begin
CountryList := TDictionary<integer, String>.Create;
UC := UniConnection2;
UQ := TUniQuery.Create(nil);
try
UQ.Connection := UC;
try
UQ.SQL.Clear;
UQ.SQL.Add('SELECT ID,NAME FROM COUNTRY ORDER BY NAME ASC');
UQ.Open;
while not UQ.Eof do
begin
CountryList.Add(UQ.Fields.FieldByName('ID').AsInteger,UQ.Fields.FieldByName('NAME').AsString);
UQ.Next;
end;
Result := CountryList;
except
on E:Exception do
ModuleMsgDialog.WarningMsg(E.Message);
end;
finally
UQ.Close;
UQ.Free;
CountryList.Free;
end;
end;
function CreateAndPopulateCountryDict: TDictionary<Integer, string>;
begin
Result := TDictionary<Integer, string>.Create;
try
// populate Result here
except
Result.Free; // until this function returns, we are responsible for lifetime
raise;
end;
end;
var
Countries: TDictionary<Integer, string>
....
Countries := CreateAndPopulateCountryDict;
try
// do stuff with Countries
finally
Countries.Free;
end;
var
国家:t词典
....
国家:=CreateAndPopulateCountryDict;
尝试
//与国家打交道
最后
国家。免费;
结束;
您应该在FormCreate方法中创建词典,并销毁或清除您需要的位置。不在LoadCountryList函数中 作为David答案的扩展,还有另一个使用回调的选项
procedure LoadCountryList( ACallback : TProc<TDictionary<integer,string>> );
var
LCountryList : TDictionary<integer,string>;
begin
// create the instance
LCountryList := TDictionary<integer,string>.Create;
try
// fill the dictionary
// execute the callback
ACallback( LCountryList );
finally
// free the instance
LCountryList.Free;
end;
end;
procedure-LoadCountryList(ACallback:TProc);
变量
LCountryList:TDictionary;
开始
//创建实例
LCountryList:=TDictionary.Create;
尝试
//查字典
//执行回调
ACallback(LContrylist);
最后
//释放实例
自由的;
结束;
结束;
然后在代码中使用它
procedure TCompanyDetailsForm.FormCreate(Sender: TObject);
begin
PageControl1.ActivePage := AddressTab;
LoadCountryList(
procedure ( CountryList : TDictionary<integer,string> )
var
i: Integer;
begin
for i in CountryList.Keys do
begin
LocationCbbx.Items.AddObject(CountryList.Items[i],TObject(i));
end;
end );
end;
过程tcompanydailsform.FormCreate(发送方:TObject);
开始
PageControl1.ActivePage:=地址选项卡;
加载国家列表(
程序(国家列表:t词典)
变量
i:整数;
开始
因为我在CountryList中。按键可以
开始
LocationCbbx.Items.AddObject(CountryList.Items[i],TObject(i));
结束;
(完),;
结束;
您应该使用类似于过程TModuleDatabase.LoadCountryList(国家/地区:TDictionary)代码>。这样,调用代码将(必须)提供字典的一个实例,调用方还将负责在需要时释放字典。您可能会将TDictionary设置为TModuleDatabase的一个字段,并且您的所有表单都可以共享同一个实例,而不是各自拥有副本。是的。。对我不这么认为。我想我会选择选项1,因为它更安全,足以满足我的需要。选项2使我不得不更加小心地使用try子句。谢谢大卫的快速回复。是的,我同意你的看法。大卫先生的回答也很清楚地回答了我的问题。谢谢你的帮助。这里有更高级的解决方案。去罗马有很多方法。我认为这个答案对我的问题来说太过分了但这也很有用。谢谢你的帮助。