Delphi XE3试图释放FSQL时无效指针(TStringList)

我在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',我得到了同样的结果。

这是我得到的错误:

项目:PayorUpdate.exe引发异常类EInvalidPointer消息'无效的指针操作。

当我打破蓝色箭头(调试模式)指向_FreeMem(指针(Self)); 在System单元中的程序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'域支持):

    procedure TPayorDM._psetSQL(const Value: TStringList);
    begin
      FSQL := Value;
    end;
    

    在这里,您将丢失对现有字符串列表(LHS)的引用。 考虑以下情况:

    你打电话

    PayorDM.SQL := AStringList;
    

    并且您在构造函数中创建的私有字段的引用已消失,而是保留对“AStringList”的引用。 之后,在某些时候你销毁'AStringList',现在'FSQL'字段是一个陈旧的指针。 当你在调用析构函数时

    FSQL.Free;
    

    你会得到一个无效的指针操作。

    改变你的二传手:

    procedure TPayorDM._psetSQL(const Value: TStringList);
    begin
      FSQL.Assign(Value);
    end;
    
    链接地址: http://www.djcxy.com/p/35017.html

    上一篇: Delphi XE3 Invalid Pointer when trying to free FSQL (TStringList)

    下一篇: Setting caption for Virtual Tree List nodes