我正在XE3中创建一个新应用程序,但使用在D2007中创建的一些单元。
我“在释放TStringList数据项时收到错误。这是创建数据项FSQL的代码:
procedure TPayorDM.DataModuleCreate(Sender: TObject);
begin
FPayorDRM := TDRM.Create;
FSQL := TStringList.Create;
end;
以下是获取错误的代码:
procedure TPayorDM.DataModuleDestroy(Sender: TObject);
begin
FreeAndNil(FSQL);
if T_Payor.Active then T_Payor.Close;
FreeAndNil(FPayorDRM);
end;
错误发生在“FreeAndNil(FSQL);”上。我尝试了“FSQL. Free”,得到了相同的结果。
这是我得到的错误:
项目:PayrUpdate。exe引发了异常类EInvalidPointer,并显示消息“指针操作无效”。
当我打破蓝色箭头(调试模式)是指向_FreeMem(指针(自我));在过程中TObject. FreeInstance在系统单元如下:
procedure TObject.FreeInstance;
begin
CleanupInstance;
_FreeMem(Pointer(Self));
end;
如果我不释放TStringList数据项,我会在应用程序中出现内存泄漏。
是否可能需要设置配置选项?我在谷歌上搜索过,除了以下三种可能性中的一种之外,没有找到任何可以解释我做错了什么的东西:
如果我试一试...除了...我可以绕过这个问题,但我不喜欢这样做。
顺便说一句,我在不同的单元中有另一个TStringList,我创建了和FreeAndNil,我没有得到任何错误。
以下是完整的来源:
unit PayorDataMgr; interface uses SysUtils, Classes, Dialogs, NativeXML, adscnnct, DB, adsdata, adsfunc, adstable, ace, cbs.drm, cbs.utils, cbs.LogFiles; const POLICY_TYPES: array[1..3] of string = ('Primary','Secondary','Tertiary'); type TPayorRecord = Record ASSIGNBENEFITS: Boolean; AUTHORIZE: Boolean; BATCHBILL: Boolean; CLAIMMAX: Integer; DISCONTINUED: TDateTime; DISPENSEUPDATE: Boolean; EHRSIGNOFF: Boolean; EMCDEST: String; FORM: String; GOVASSIGN: Boolean; HIDE: Boolean; IGRPUNIQUE: Integer; LEGACYPLAN: String; LEGACYTYPE: String; LOCALATTN: String; LOCALCITY: String; LOCALNAME: String; LOCALPHONE: String; LOCALSTATE: String; LOCALSTREET: String; LOCALZIP: String; MASTERATTN: String; MASTERCITY: String; MASTERNAME: String; MASTERPHONE: String; MASTERSTATE: String; MASTERSTREET: String; MASTERZIP: String; MEDIGAPCODE: String; MEDIGAPPAYOR: Boolean; MEDPLANGUID: String; MODIFIED: TDateTime; NEICCODE: String; NEICTYPESTDC: Integer; OWNER: String; PAYORGUID: String; PAYORSUBTYPESTDC: Integer; PAYORTYPESTDC: Integer; PAYORUNIQUE: Integer; PAYPERCENT: Integer; RTCODE: String; SRXPLANGUID: String; STATEFILTER: String; procedure Clear; End; TPayors = Record private function _pGetCount: Integer; public Items: Array of TPayorRecord; procedure Add(const aItem:TPayorRecord); function CarriersList:TStrings; procedure Free; function GetPayorGuid(const aPAYORUNIQUE:Integer):String; function IndexOfIgrpUnique(Const aIGRPUNIQUE:Integer):Integer; function IndexOfPayorUnique(Const aPAYORUNIQUE:Integer):Integer; procedure SortByName; property Count:Integer Read _pGetCount; End; TPayorDM = class(TDataModule) CommonConnection: TAdsConnection; T_Payor: TAdsTable; Q_Payor: TAdsQuery; procedure DataModuleDestroy(Sender: TObject); procedure DataModuleCreate(Sender: TObject); private FPayorDRM: TDRM; FSQL: TStringList; function _LoadRecordFromTable:TPayorRecord; function _newIDSTRING(const aFormat:String='F'):String; { Private declarations } procedure _pSetConnectionHandle(const Value: Integer); procedure _pSetErrorMessage(const Value: String); procedure _psetSQL(const Value: TStringList); { Private properties } property ErrorMessage:String Write _pSetErrorMessage; public function AddPayor(var aPAYORRECORD:TPAYORRECORD):Boolean; function ExecuteScript(const aTo,aFrom:string):Boolean; function FindPayor(const aPAYORGUID:String):Boolean;overload; function FindPayor(const aPAYORUNIQUE:Integer):Boolean;overload; function GetPayorData:TDRM; function GetRecordCount(const aData:String):Integer; function LoadCarriers(const aHide:boolean = False):TPayors; function LoadPayor:TPayorRecord; function OpenTable:Boolean; function UpdateFromXML(const aPayorNode:TXMLNode):boolean; { Public declarations } property ConnectionHandle:Integer Write _pSetConnectionHandle; property DynamicPayorFields:TDRM Read FPayorDRM; property SQL:TStringList Read FSQL Write _psetSQL; end; var PayorDM: TPayorDM; implementation {$R *.dfm} function TPayorDM.AddPayor(var aPAYORRECORD: TPAYORRECORD): Boolean; begin Result := False; if IsNull(aPAYORRECORD.LOCALNAME) then Exit; { Create uniques } { Add Record } if not T_Payor.Active then if not OpenTable then Exit; with T_Payor do try Insert; FieldByName('PAYORGUID').AsString := _newIDSTRING; FieldByName('MASTERNAME').AsString := aPAYORRECORD.MASTERNAME; FieldByName('MASTERSTREET').AsString := aPAYORRECORD.MASTERSTREET; FieldByName('MASTERCITY').AsString := aPAYORRECORD.MASTERCITY; FieldByName('MASTERSTATE').AsString := aPAYORRECORD.MASTERSTATE; FieldByName('PAYORTYPESTDC').AsInteger := aPAYORRECORD.PAYORTYPESTDC; FieldByName('MASTERZIP').AsString := aPAYORRECORD.MASTERZIP; FieldByName('MASTERATTN').AsString := aPAYORRECORD.MASTERATTN; FieldByName('MASTERPHONE').AsString := aPAYORRECORD.MASTERPHONE; FieldByName('NEICCODE').AsString := aPAYORRECORD.NEICCODE; FieldByName('RTCODE').AsString := aPAYORRECORD.RTCODE; FieldByName('STATEFILTER').AsString := aPAYORRECORD.STATEFILTER; FieldByName('NEICTYPESTDC').AsInteger := aPAYORRECORD.NEICTYPESTDC; FieldByName('PAYORSUBTYPESTDC').AsInteger := aPAYORRECORD.PAYORSUBTYPESTDC; FieldByName('OWNER').AsString := aPAYORRECORD.OWNER; FieldByName('HIDE').AsBoolean := aPAYORRECORD.HIDE; FieldByName('IGRPUNIQUE').AsInteger := aPAYORRECORD.IGRPUNIQUE; FieldByName('FORM').AsString := aPAYORRECORD.FORM; FieldByName('GOVASSIGN').AsBoolean := aPAYORRECORD.GOVASSIGN; FieldByName('CLAIMMAX').AsInteger := aPAYORRECORD.CLAIMMAX; FieldByName('MEDIGAPCODE').AsString := aPAYORRECORD.MEDIGAPCODE; FieldByName('EMCDEST').AsString := aPAYORRECORD.EMCDEST; FieldByName('ASSIGNBENEFITS').AsBoolean := aPAYORRECORD.ASSIGNBENEFITS; FieldByName('BATCHBILL').AsBoolean := aPAYORRECORD.BATCHBILL; FieldByName('MEDIGAPPAYOR').AsBoolean := aPAYORRECORD.MEDIGAPPAYOR; FieldByName('MEDPLANGUID').AsString := aPAYORRECORD.MEDPLANGUID; FieldByName('SRXPLANGUID').AsString := aPAYORRECORD.SRXPLANGUID; FieldByName('PAYPERCENT').AsInteger := aPAYORRECORD.PAYPERCENT; FieldByName('LOCALNAME').AsString := aPAYORRECORD.LOCALNAME; FieldByName('LOCALSTREET').AsString := aPAYORRECORD.LOCALSTREET; FieldByName('LOCALCITY').AsString := aPAYORRECORD.LOCALCITY; FieldByName('LOCALSTATE').AsString := aPAYORRECORD.LOCALSTATE; FieldByName('LOCALZIP').AsString := aPAYORRECORD.LOCALZIP; FieldByName('LOCALATTN').AsString := aPAYORRECORD.LOCALATTN; FieldByName('LOCALPHONE').AsString := aPAYORRECORD.LOCALPHONE; FieldByName('EHRSIGNOFF').AsBoolean := aPAYORRECORD.EHRSIGNOFF; FieldByName('DISCONTINUED').AsDateTime := aPAYORRECORD.DISCONTINUED; FieldByName('MODIFIED').AsDateTime := Now; FieldByName('LEGACYPLAN').AsString := aPAYORRECORD.LEGACYPLAN; FieldByName('LEGACYTYPE').AsString := aPAYORRECORD.LEGACYTYPE; FieldByName('AUTHORIZE').AsBoolean := aPAYORRECORD.AUTHORIZE; FieldByName('DISPENSEUPDATE').AsBoolean := aPAYORRECORD.DISPENSEUPDATE; Post; aPAYORRECORD.PAYORUNIQUE := FieldByName('PAYORUNIQUE').AsInteger; aPAYORRECORD.PAYORGUID := FieldByName('PAYORGUID').AsString; Close; Result := True; except on E: EADSDatabaseError do begin ErrorMessage := 'AddPayor: ERRORCODE: ' + IntToStr(e.ACEErrorCode) + ' ERROR: ' + e.Message; end; end; end; procedure TPayorDM.DataModuleCreate(Sender: TObject); begin FPayorDRM := TDRM.Create; FSQL := TStringList.Create; { FSQL Created } end; procedure TPayorDM.DataModuleDestroy(Sender: TObject); begin try FSQL.Free; { FSQL destroyed - work around to get unit to run without error} except end; if T_Payor.Active then T_Payor.Close; FreeAndNil(FPayorDRM); end; function TPayorDM.ExecuteScript(const aTo, aFrom: string):Boolean; begin Result := False; if FSQL.Count = 0 then exit; with Q_Payor do try if Active then Close; SQL := FSQL; ParamByName('to').Text := aTo; ParambyName('from').Text := aFrom; ExecSQL; if Active then Close; Result := True; except on E: EADSDatabaseError do begin ErrorMessage := 'ExecuteScript: ERRORCODE: ' + IntToStr(e.ACEErrorCode) + ' ERROR: ' + e.Message + ' SQL: ' + Q_Payor.SQL.Text; end; end; end; function TPayorDM.FindPayor(const aPAYORUNIQUE: Integer): Boolean; begin T_Payor.IndexName := 'PAYORUNIQUE'; Result := T_Payor.FindKey([aPAYORUNIQUE]); end; function TPayorDM.FindPayor(const aPAYORGUID: String): Boolean; begin T_Payor.IndexName := 'PAYORGUID'; Result := T_Payor.FindKey([aPAYORGUID]); end; function TPayorDM.GetPayorData: TDRM; begin if FPayorDRM.Count = 0 then FPayorDRM.BuildDRMList(T_Payor); Result := FPayorDRM; end; function TPayorDM.GetRecordCount(const aData:string): Integer; begin Result := 0; if FSQL.Count = 0 then exit; with Q_Payor do try if Active then Close; SQL := FSQL; ParamByName('data').AsString := aData; Open; Result := RecordCount; Close; except on E: EADSDatabaseError do begin ErrorMessage := 'GetRecordCount: ERRORCODE: ' + IntToStr(e.ACEErrorCode) + ' ERROR: ' + e.Message; end; end; end; function TPayorDM.LoadCarriers(const aHide: boolean): TPayors; begin OpenTable; Result.Free; with T_Payor do begin First; while not EOF do begin if T_Payor.FieldByName('HIDE').AsBoolean = aHide then Result.Add(_LoadRecordFromTable); Next; end; First; Result.SortByName; end; end; function TPayorDM.LoadPayor: TPayorRecord; begin Result.Clear; try if not T_Payor.active then exit; if T_Payor.RecNo = 0 then exit; Result := _LoadRecordFromTable; except on E: EADSDatabaseError do begin ErrorMessage := 'LoadPayor: ERRORCODE: ' + IntToStr(e.ACEErrorCode) + ' ERROR: ' + e.Message; end; end; end; function TPayorDM.OpenTable: Boolean; begin Result := False; with T_Payor do try if not Active then Open; FPayorDRM.BuildDRMList(T_Payor); FPayorDRM.LoadValues(T_Payor); { test } FPayorDRM.ExportDRMList; { test } Result := True; except on E: EADSDatabaseError do begin ErrorMessage := 'OpenTable: ERRORCODE: ' + IntToStr(e.ACEErrorCode) + ' ERROR: ' + e.Message; end; end; end; function TPayorDM.UpdateFromXML(const aPayorNode: TXMLNode): boolean; var fKeyData:TXMLNode; Idx,fPAYORUNIQUE:Integer; begin Result := False; if not Assigned(aPayorNode) then Exit; try if FPayorDRM.Count = 0 then FPayorDRM.BuildDRMList(T_Payor); FPayorDRM.ClearValues; fKeyData := aPayorNode.FindNode('KeyData'); FPayorDRM.FindRecordFromKeyData(fKeyData,T_Payor); fPAYORUNIQUE := FPayorDRM.FieldByName('PAYORUNIQUE').AsInteger; FPayorDRM.LoadValues(aPayorNode); if fPAYORUNIQUE = 0 then begin FPayorDRM.FieldByName('PAYORUNIQUE').AsInteger := 0; FPayorDRM.FieldByName('PAYORGUID').AsString := _newIDSTRING; FPayorDRM.FieldByName('MODIFIED').AsDate := Now; FPayorDRM.AddRecord(T_Payor) end else begin FPayorDRM.FieldByName('MODIFIED').AsDate := Now; FPayorDRM.UpdateRecord(T_Payor); end; except on e:exception do begin ErrorMessage := 'UpdateFromXML: ERROR: ' + e.Message; end; end; end; function TPayorDM._LoadRecordFromTable: TPayorRecord; begin with T_Payor do begin Result.PAYORUNIQUE := FieldByName('PAYORUNIQUE').AsInteger; Result.PAYORGUID := FieldByName('PAYORGUID').AsString; Result.MASTERNAME := FieldByName('MASTERNAME').AsString; Result.MASTERSTREET := FieldByName('MASTERSTREET').AsString; Result.MASTERCITY := FieldByName('MASTERCITY').AsString; Result.MASTERSTATE := FieldByName('MASTERSTATE').AsString; Result.PAYORTYPESTDC := FieldByName('PAYORTYPESTDC').AsInteger; Result.MASTERZIP := FieldByName('MASTERZIP').AsString; Result.MASTERATTN := FieldByName('MASTERATTN').AsString; Result.MASTERPHONE := FieldByName('MASTERPHONE').AsString; Result.NEICCODE := FieldByName('NEICCODE').AsString; Result.RTCODE := FieldByName('RTCODE').AsString; Result.STATEFILTER := FieldByName('STATEFILTER').AsString; Result.NEICTYPESTDC := FieldByName('NEICTYPESTDC').AsInteger; Result.PAYORSUBTYPESTDC := FieldByName('PAYORSUBTYPESTDC').AsInteger; Result.OWNER := FieldByName('OWNER').AsString; Result.HIDE := FieldByName('HIDE').AsBoolean; Result.IGRPUNIQUE := FieldByName('IGRPUNIQUE').AsInteger; Result.FORM := FieldByName('FORM').AsString; Result.GOVASSIGN := FieldByName('GOVASSIGN').AsBoolean; Result.CLAIMMAX := FieldByName('CLAIMMAX').AsInteger; Result.MEDIGAPCODE := FieldByName('MEDIGAPCODE').AsString; Result.EMCDEST := FieldByName('EMCDEST').AsString; Result.ASSIGNBENEFITS := FieldByName('ASSIGNBENEFITS').AsBoolean; Result.BATCHBILL := FieldByName('BATCHBILL').AsBoolean; Result.MEDIGAPPAYOR := FieldByName('MEDIGAPPAYOR').AsBoolean; Result.MEDPLANGUID := FieldByName('MEDPLANGUID').AsString; Result.SRXPLANGUID := FieldByName('SRXPLANGUID').AsString; Result.PAYPERCENT := FieldByName('PAYPERCENT').AsInteger; Result.LOCALNAME := FieldByName('LOCALNAME').AsString; Result.LOCALSTREET := FieldByName('LOCALSTREET').AsString; Result.LOCALCITY := FieldByName('LOCALCITY').AsString; Result.LOCALSTATE := FieldByName('LOCALSTATE').AsString; Result.LOCALZIP := FieldByName('LOCALZIP').AsString; Result.LOCALATTN := FieldByName('LOCALATTN').AsString; Result.LOCALPHONE := FieldByName('LOCALPHONE').AsString; Result.EHRSIGNOFF := FieldByName('EHRSIGNOFF').AsBoolean; Result.DISCONTINUED := FieldByName('DISCONTINUED').AsDateTime; Result.MODIFIED := FieldByName('MODIFIED').AsDateTime; Result.LEGACYPLAN := FieldByName('LEGACYPLAN').AsString; Result.LEGACYTYPE := FieldByName('LEGACYTYPE').AsString; Result.AUTHORIZE := FieldByName('AUTHORIZE').AsBoolean; Result.DISPENSEUPDATE := FieldByName('DISPENSEUPDATE').AsBoolean; end; end; function TPayorDM._newIDSTRING(const aFormat: String): String; begin Result := ''; try with Q_Payor do try SQL.Clear; SQL.Add('SELECT NEWIDSTRING( "' + aFormat + '" ) AS GUID FROM system.iota'); Open; Result := FieldByName('GUID').AsString; Close; except on E: EADSDatabaseError do begin ErrorMessage := '_newIDSTRING: ERRORCODE: ' + IntToStr(e.ACEErrorCode) + ' ERROR: ' + e.Message; end; end; finally end; end; procedure TPayorDM._pSetConnectionHandle(const Value: Integer); begin if T_Payor.Active then T_Payor.Close; CommonConnection.SetHandle(Value); OpenTable; end; procedure TPayorDM._pSetErrorMessage(const Value: String); begin WriteError('[TPayorDM]' + Value,LogFilename); end; procedure TPayorDM._psetSQL(const Value: TStringList); begin FSQL := Value; end; { TPayorRecord } procedure TPayorRecord.Clear; begin PAYORUNIQUE := 0; PAYORGUID := ''; MASTERNAME := ''; MASTERSTREET := ''; MASTERCITY := ''; MASTERSTATE := ''; PAYORTYPESTDC := 0; MASTERZIP := ''; MASTERATTN := ''; MASTERPHONE := ''; NEICCODE := ''; RTCODE := ''; STATEFILTER := ''; NEICTYPESTDC := 0; PAYORSUBTYPESTDC := 0; OWNER := ''; HIDE := False; IGRPUNIQUE := 0; FORM := ''; GOVASSIGN := False; CLAIMMAX := 0; MEDIGAPCODE := ''; EMCDEST := ''; ASSIGNBENEFITS := False; BATCHBILL := False; MEDIGAPPAYOR := False; MEDPLANGUID := ''; SRXPLANGUID := ''; PAYPERCENT := 0; LOCALNAME := ''; LOCALSTREET := ''; LOCALCITY := ''; LOCALSTATE := ''; LOCALZIP := ''; LOCALATTN := ''; LOCALPHONE := ''; EHRSIGNOFF := False; DISCONTINUED := 0; MODIFIED := 0; LEGACYPLAN := ''; LEGACYTYPE := ''; AUTHORIZE := False; DISPENSEUPDATE := False; end; { TPayors } procedure TPayors.Add(const aItem: TPayorRecord); begin SetLength(Items,Count + 1); Items[Count - 1] := aItem; end; function TPayors.CarriersList: TStrings; var I: Integer; begin Result := TStringList.Create; Result.Clear; SortbyName; try for I := 0 to Count - 1 do Result.Add(Items[I].LOCALNAME); finally end; end; procedure TPayors.Free; begin Items := Nil; end; function TPayors.GetPayorGuid(const aPAYORUNIQUE: Integer): String; var Idx:Integer; begin Result := ''; Idx := IndexOfPayorUnique(aPAYORUNIQUE); if not (Idx = -1) then Result := Items[Idx].PAYORGUID; end; function TPayors.IndexOfIgrpUnique(const aIGRPUNIQUE: Integer): Integer; var I: Integer; begin Result := -1; for I := 0 to Count - 1 do if Items[I].IGRPUNIQUE = aIGRPUNIQUE then begin Result := I; Break; end; end; function TPayors.IndexOfPayorUnique(const aPAYORUNIQUE: Integer): Integer; var I: Integer; begin Result := -1; for I := 0 to Count - 1 do if Items[I].PAYORUNIQUE = aPAYORUNIQUE then begin Result := I; Break; end; end; procedure TPayors.SortByName; var fSort:TStringList; fParse:TStrings; I,Idx: Integer; fTempPayor:TPayors; begin fSort := TStringList.Create; fParse := TStringList.Create; fTempPayor.Items := Self.Items; fSort.Sorted := True; try for I := 0 to Count - 1 do fSort.Add(Items[I].LOCALNAME + #9 + IntToStr(I)); Items := Nil; for I := 0 to fSort.Count - 1 do begin cbs.utils.ParseDelimited(fParse,fSort[I],#9); Idx := StrToInt(fParse[1]); Add(fTempPayor.Items[Idx]); end; finally fTempPayor.Free; fParse.Free; fSort.Free; end; end; function TPayors._pGetCount: Integer; begin Result := Length(Items); end; end.
您(很可能)正在双重释放一个字符串列表(并且永远不会释放至少一个)。问题出在您的“SQL”属性(由“FSQL”字段支持)的setter中:
procedure TPayorDM._psetSQL(const Value: TStringList);
begin
FSQL := Value;
end;
在这里,您将失去对已经存在的字符串列表(LHS)的引用。考虑以下场景:
你打电话
PayorDM.SQL := AStringList;
并且您在构造函数中创建的对私有字段的引用也消失了,相反,您保留了对“AStringList”的引用。之后,在某个点上销毁了“AStringList”,现在“FSQL”字段是一个过时的指针。在析构函数中调用
FSQL.Free;
您得到的指针操作无效。
将您的setter更改为:
procedure TPayorDM._psetSQL(const Value: TStringList);
begin
FSQL.Assign(Value);
end;
本文向大家介绍什么是指针的释放? 相关面试题,主要包含被问及什么是指针的释放? 时的应答技巧和注意事项,需要的朋友参考一下 具体来说包括两个概念. 1 释放该指针指向的内存,只有堆上的内存才需要我们手工释放,栈上不需要. 2 将该指针重定向为NULL.
问题内容: 我想从带有ctypes的C / C ++库中获取一些字符串到python中。我的代码如下所示: lib中的代码: Python代码: 如果我print()c_str,一切都在那里。问题是(或似乎是)在最后一行Python中。我无法释放内存- 库得到了错误的指针。我在这里做错了什么?(并且请不要建议boost :: python左右)。 问题答案: 正如David Schwartz指出的
我有一个类(A),它包含另一个类(B)的自动生成依赖项,而另一个类(B)又具有另一个类C的自动生成依赖项。 我正在尝试使用Mockito编写测试用例,并对依赖项使用spy注释。我在监视C类时遇到空指针错误。 如何从A类执行此单元测试?
我得到的只有java.lang.NullPointerException。 我还尝试了各种命名风格,如java:jdbc/mydb或java:comp/env/jdbc/mydb 这使用了最新的Glassfish(4.1),针对Postgres 9.4的最新Postgres驱动程序(9.3-1102 JDBC 41),以及最新的Java(1.8.0_31-B13)。
根据我的理解, free()用于释放之前使用malloc分配的内存。 在我下面的片段中,我释放了我分配的内存。但是即使释放后我也能够访问指针?这怎么可能? free如何在内部工作?
背景: 我有C背景,刚开始在嵌入式项目中使用C++。 我编写了一个能够处理多个设备的固件,具体取决于最终用户获得设备之前如何通过图形界面配置固件。 每个设备类型由一个类表示。 许多参数在多个(但不是所有)类型的器件之间共享(即电池电平),一些功能也共享(即从EEPROM读取特定于器件类型的内容)。 目标: 能够通过指针访问函数和变量,而不必不断转换void指针。 在调用函数之前,我不应该知道我使用