0

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(Pointer(Self)); を指しています。System ユニットのプロシージャ TObject.FreeInstance では、次のようになります。

procedure TObject.FreeInstance;
begin
  CleanupInstance;
  _FreeMem(Pointer(Self));
end;

TStringList データ項目を解放しないと、アプリでメモリ リークが発生します。

設定する必要がある構成オプションはありますか? 私はグーグルで検索しましたが、3つの可能性の1つ以外に、私が間違っていることを説明するものは何も見つかりませんでした:

  • 他のメモリ マネージャによって割り当てられました。
  • 以前に一度解放されていました。
  • それは何によっても割り当てられたことはありませんでした。

試してみると...ただし...問題を回避することはできますが、これは避けたいと思います。

ところで、別のユニットに別の TStringList があり、FreeAndNil を作成しましたが、エラーは発生しません。

ソース全体は次のとおりです。

    ユニット PayorDataMgr;

    インターフェース

    用途
      システムユーティリティ、
      クラス、
      ダイアログ、
      NativeXML、
      副次的、
      DB、
      広告データ、
      広告機能、
      アドスタブル、
      エース、
      cbs.drm、
      cbs.utils、
      cbs.LogFiles;

    定数
      POLICY_TYPES: 文字列の配列[1..3] = ('Primary','Secondary','Tertiary');

    タイプ
      TPayorRecord = レコード
        ASSIGNBENEFITS: ブール値。
        承認: ブール値。
        BATCHBILL: ブール値。
        CLAIMMAX: 整数。
        廃止: TDateTime;
        DISPENSEUPDATE: ブール値;
        EHRSIGNOFF: ブール値。
        EMCDEST: 文字列;
        フォーム: 文字列;
        GOVASSIGN: ブール値;
        非表示: ブール値。
        IGRPUNIQUE: 整数。
        レガシープラン: 文字列;
        LEGACYTYPE: 文字列;
        LOCALATTN: 文字列;
        LOCALCITY: 文字列;
        LOCALNAME: 文字列;
        LOCALPHONE: 文字列;
        LOCALSTATE: 文字列;
        LOCALSTREET: 文字列;
        LOCALZIP: 文字列;
        MASTERATTN: 文字列;
        MASTERCITY: 文字列;
        MASTERNAME: 文字列;
        MASTERPHONE: 文字列;
        MASTERSTATE: 文字列;
        マスターストリート: 文字列;
        MASTERZIP: 文字列;
        MEDIGAPCODE: 文字列;
        MEDIGAPPAYOR: ブール値。
        MEDPLANGUID: 文字列;
        変更: TDateTime;
        NEICCODE: 文字列;
        NEICTYPESTDC: 整数。
        所有者: 文字列;
        PAYORGUID: 文字列。
        PAYORSUBTYPESTDC: 整数;
        PAYORTYPESTDC: 整数;
        PAYORUNIQUE: 整数。
        PAYPERCENT: 整数。
        RTCODE: 文字列;
        SRXPLANGUID: 文字列;
        STATEFILTER: 文字列;
        手順 クリア;
      終わり;

      TPayors = レコード
      プライベート
        関数 _pGetCount: 整数;
      公衆
        項目: TPayorRecord の配列。
        procedure Add(const aItem:TPayorRecord);
        関数 CarriersList:TStrings;
        手続き無料。
        function GetPayorGuid(const aPAYORUNIQUE:Integer):String;
        function IndexOfIgrpUnique(Const aIGRPUNIQUE:Integer):Integer;
        function IndexOfPayorUnique(Const aPAYORUNIQUE:Integer):Integer;
        手順SortByName;
        プロパティ カウント:整数 読み取り _pGetCount;
      終わり;

      TPayorDM = クラス(TDataModule)
        CommonConnection: TAdsConnection;
        T_Payor: TAdsTable;
        Q_Payor: TAdsQuery;
        procedure DataModuleDestroy(Sender: TObject);
        procedure DataModuleCreate(Sender: TObject);
      プライベート
        FPayorDRM: ​​TDRM;
        FSQL: TStringList;
        function _LoadRecordFromTable:TPayorRecord;
        function _newIDSTRING(const aFormat:String='F'):String;
        { 私的宣言 }
        procedure _pSetConnectionHandle(const 値: 整数);
        procedure _pSetErrorMessage(const 値: 文字列);
        プロシージャ _psetSQL(const 値: TStringList);

        { 私有財産 }
        プロパティ ErrorMessage:String Write _pSetErrorMessage;
      公衆
        function AddPayor(var aPAYORRECORD:TPAYORRECORD):Boolean;
        function ExecuteScript(const aTo,aFrom:string):Boolean;
        関数 FindPayor(const aPAYORGUID:String):Boolean;オーバーロード;
        function FindPayor(const aPAYORUNIQUE:Integer):Boolean;オーバーロード;
        関数 GetPayorData:TDRM;
        function GetRecordCount(const aData:String):Integer;
        関数 LoadCarriers(const aHide:boolean = False):TPayors;
        関数 LoadPayor:TPayorRecord;
        関数 OpenTable:ブール値;
        function UpdateFromXML(const aPayorNode:TXMLNode):boolean;
        {公開宣言}
        property ConnectionHandle:Integer Write _pSetConnectionHandle;
        プロパティ DynamicPayorFields:TDRM FPayorDRM を読み取ります。
        プロパティ SQL:TStringList 読み取り FSQL 書き込み _psetSQL;
      終わり;

    変数
      PayorDM: TPayorDM;

    実装

    {$R *.dfm}

    function TPayorDM.AddPayor(var aPAYORRECORD: TPAYORRECORD): Boolean;
    始める
      結果:=偽;
      If IsNull(aPAYORRECORD.LOCALNAME) then Exit;
      {ユニークを作成する}

      {レコードを追加}
      T_Payor.Active でない場合
        OpenTable でない場合は終了します。
      T_Payor doで
      試す
        入れる;
        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 := 今;
        FieldByName('LEGACYPLAN').AsString := aPAYORRECORD.LEGACYPLAN;
        FieldByName('LEGACYTYPE').AsString := aPAYORRECORD.LEGACYTYPE;
        FieldByName('AUTHORIZE').AsBoolean := aPAYORRECORD.AUTHORIZE;
        FieldByName('DISPENSEUPDATE').AsBoolean := aPAYORRECORD.DISPENSEUPDATE;
        役職;
        aPAYORRECORD.PAYORUNIQUE := FieldByName('PAYORUNIQUE').AsInteger;
        aPAYORRECORD.PAYORGUID := FieldByName('PAYORGUID').AsString;
        近い;
        結果:=真;
      E: EADSDatabaseError do を除く
      始める
        ErrorMessage := 'AddPayor: ERRORCODE: ' + IntToStr(e.ACEErrorCode) +
          ' エラー: ' + e.Message;
      終わり;
      終わり;
    終わり;

    procedure TPayorDM.DataModuleCreate(Sender: TObject);
    始める
      FPayorDRM := TDRM.Create;
      FSQL := TStringList.Create; { FSQL が作成されました }
   終わり;

    procedure TPayorDM.DataModuleDestroy(送信者: TObject);
    始める
      試す
        FSQL.Free; { FSQL が破壊されました - ユニットをエラーなしで実行できるように回避します}
      を除外する

      終わり;
      T_Payor.Active の場合、T_Payor.Close;
      FreeAndNil(FPayorDRM);
    終わり;

    function TPayorDM.ExecuteScript(const aTo, aFrom: string):Boolean;
    始める
      結果:=偽;
      FSQL.Count = 0 の場合は終了します。
      Q_Payor doで
      試す
        アクティブの場合はクローズ。
        SQL := FSQL;
        ParamByName('to').Text := aTo;
        ParambyName('from').Text := aFrom;
        ExecSQL;
        アクティブの場合はクローズ。
        結果:=真;
      E: EADSDatabaseError do を除く
      始める
        ErrorMessage := 'ExecuteScript: ERRORCODE: ' + IntToStr(e.ACEErrorCode) +
          ' エラー: ' + e.Message + ' SQL: ' + Q_Payor.SQL.Text;
      終わり;
      終わり;
    終わり;

    function TPayorDM.FindPayor(const aPAYORUNIQUE: Integer): Boolean;
    始める
      T_Payor.IndexName := 'PAYORUNIQUE';
      結果:= T_Payor.FindKey([aPAYORUNIQUE]);
    終わり;

    function TPayorDM.FindPayor(const aPAYORGUID: String): Boolean;
    始める
      T_Payor.IndexName := 'PAYORGUID';
      結果:= T_Payor.FindKey([PAYORGUID]);
    終わり;

    関数 TPayorDM.GetPayorData: TDRM;
    始める
      FPayorDRM.Count = 0 の場合
        FPayorDRM.BuildDRMList(T_Payor);
      結果:= FPayorDRM;
    終わり;


    function TPayorDM.GetRecordCount(const aData:string): Integer;
    始める
      結果:= 0;
      FSQL.Count = 0 の場合は終了します。
      Q_Payor doで
      試す
        アクティブの場合はクローズ。
        SQL := FSQL;
        ParamByName('data').AsString := aData;
        開ける;
        結果:= RecordCount;
        近い;
      E: EADSDatabaseError do を除く
      始める
        ErrorMessage := 'GetRecordCount: ERRORCODE: ' + IntToStr(e.ACEErrorCode) +
          ' エラー: ' + e.Message;
      終わり;
      終わり;

    終わり;

    function TPayorDM.LoadCarriers(const aHide: boolean): TPayors;
    始める
      OpenTable;
      Result.Free;
      T_Payor doで
      始める
        初め;
        EOF ではない間
        始める
          T_Payor.FieldByName('HIDE').AsBoolean = aHide の場合
            Result.Add(_LoadRecordFromTable);
          次;
        終わり;
        初め;
        Result.SortByName;
      終わり;
    終わり;

    関数 TPayorDM.LoadPayor: TPayorRecord;
    始める
      結果.クリア;
      試す
        T_Payor.active でない場合は終了します。
        T_Payor.RecNo = 0 の場合は終了します。
        結果:= _LoadRecordFromTable;
      E: EADSDatabaseError do を除く
      始める
        ErrorMessage := 'LoadPayor: ERRORCODE: ' + IntToStr(e.ACEErrorCode) +
          ' エラー: ' + e.Message;
      終わり;
      終わり;
    終わり;

    関数 TPayorDM.OpenTable: ブール値;
    始める
      結果:=偽;
      T_Payor doで
      試す
        アクティブでない場合はオープン。
        FPayorDRM.BuildDRMList(T_Payor);
        FPayorDRM.LoadValues(T_Payor); { テスト }
        FPayorDRM.ExportDRMList; { テスト }
        結果:=真;
      E: EADSDatabaseError do を除く
      始める
        ErrorMessage := 'OpenTable: ERRORCODE: ' + IntToStr(e.ACEErrorCode) +
          ' エラー: ' + e.Message;
      終わり;
      終わり;
    終わり;

    function TPayorDM.UpdateFromXML(const aPayorNode: TXMLNode): boolean;
    変数
      fKeyData:TXMLNode;
      Idx,fPAYORUNIQUE:整数;
    始める
      結果:=偽;
      割り当てられていない場合(aPayorNode)、終了します。
      試す
        FPayorDRM.Count = 0 の場合
          FPayorDRM.BuildDRMList(T_Payor);
        FPayorDRM.ClearValues;
        fKeyData := aPayorNode.FindNode('KeyData');
        FPayorDRM.FindRecordFromKeyData(fKeyData,T_Payor);
        fPAYORUNIQUE := FPayorDRM.FieldByName('PAYORUNIQUE').AsInteger;
        FPayorDRM.LoadValues(aPayorNode);
        fPAYORUNIQUE = 0 の場合
        始める
          FPayorDRM.FieldByName('PAYORUNIQUE').AsInteger:= 0;
          FPayorDRM.FieldByName('PAYORGUID').AsString := _newIDSTRING;
          FPayorDRM.FieldByName('MODIFIED').AsDate := 今;
          FPayorDRM.AddRecord(T_Payor)
        終わり
        そうしないと
        始める
          FPayorDRM.FieldByName('MODIFIED').AsDate := 今;
          FPayorDRM.UpdateRecord(T_Payor);
        終わり;
      e:exception do を除く
      始める
        ErrorMessage := 'UpdateFromXML: エラー: ' + e.Message;
      終わり;
      終わり;
    終わり;

    function TPayorDM._LoadRecordFromTable: TPayorRecord;
    始める
      T_Payor doで
      始める
        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;
      終わり;
    終わり;

    function TPayorDM._newIDSTRING(const aFormat: String): String;
    始める
      結果:= '';
      試す
        Q_Payor doで
        試す
          SQL.Clear;
          SQL.Add('SELECT NEWIDSTRING( "' + aFormat + '" ) AS GUID FROM system.iota');
          開ける;
          結果:= FieldByName('GUID').AsString;
          近い;
        E: EADSDatabaseError do を除く
        始める
          ErrorMessage := '_newIDSTRING: ERRORCODE: ' + IntToStr(e.ACEErrorCode) +
            ' エラー: ' + e.Message;
        終わり;
        終わり;
      最後に

      終わり;
    終わり;

    procedure TPayorDM._pSetConnectionHandle(const 値: 整数);
    始める
      T_Payor.Active の場合、T_Payor.Close;
      CommonConnection.SetHandle(値);
      OpenTable;
    終わり;

    procedure TPayorDM._pSetErrorMessage(const 値: 文字列);
    始める
      WriteError('[TPayorDM]' + Value,LogFilename);
    終わり;

    procedure TPayorDM._psetSQL(const Value: TStringList);
    始める
      FSQL := 値;
    終わり;

    { TPayorRecord }

    手順 TPayorRecord.Clear;
    始める
      パヨルニク:= 0;
      PAYORGUID := '';
      マスターネーム:= '';
      マスターストリート:= '';
      マスターシティ:= '';
      マスターステート:= '';
      PAYORTYPESTDC := 0;
      MASTERZIP := '';
      MASTERATTN := '';
      マスターフォン:= '';
      NEICCODE := '';
      RTCODE := '';
      STATEFILTER := '';
      NEICTYPESTDC := 0;
      PAYORSUBTYPESTDC := 0;
      所有者:= '';
      非表示:= 偽;
      IGRPUNIQUE := 0;
      フォーム:= '';
      GOVASSIGN := 偽;
      CLAIMMAX := 0;
      MEDIGAPCODE := '';
      EMCDEST := '';
      ASSIGNBENEFITS := 偽;
      バッチビル:=偽;
      MEDIGAPPAYOR := 偽;
      MEDPLANGUID := '';
      SRXPLANGUID := '';
      PAYPERCENT := 0;
      ローカル名:= '';
      LOCALSTREET := '';
      地域:= '';
      LOCALSTATE := '';
      LOCALZIP := '';
      LOCALATTN := '';
      LOCALPHONE := '';
      EHRSIGNOFF := 偽;
      廃止:= 0;
      変更:= 0;
      レガシープラン:= '';
      レガシータイプ:= '';
      承認:=偽;
      DISPENSEUPDATE := 偽;
    終わり;

    { 支払い者 }

    procedure TPayors.Add(const aItem: TPayorRecord);
    始める
      SetLength(アイテム,カウント + 1);
      アイテム[数 - 1] := aItem;
    終わり;

    function TPayors.CarriersList: TStrings;
    変数
      I: 整数。
    始める
      結果:= TStringList.Create;
      結果.クリア;
      名前順;
      試す
      for I := 0 to Count - 1 do
        Result.Add(Items[I].LOCALNAME);
      最後に

      終わり;
    終わり;

    手順 TPayors.Free;
    始める
      アイテム := なし;
    終わり;

    function TPayors.GetPayorGuid(const aPAYORUNIQUE: Integer): 文字列;
    変数
      Idx:整数;
    始める
      結果:= '';
      Idx := IndexOfPayorUnique(aPAYORUNIQUE);
      そうでない場合 (Idx = -1)
        結果:=アイテム[Idx].PAYORGUID;
    終わり;

    function TPayors.IndexOfIgrpUnique(const aIGRPUNIQUE: Integer): Integer;
    変数
      I: 整数。
    始める
      結果:= -1;
      for I := 0 to Count - 1 do
        If Items[I].IGRPUNIQUE = aIGRPUNIQUE then
        始める
          結果 := 私;
          壊す;
        終わり;
    終わり;

    function TPayors.IndexOfPayorUnique(const aPAYORUNIQUE: Integer): Integer;
    変数
      I: 整数。
    始める
      結果:= -1;
      for I := 0 to Count - 1 do
        if Items[I].PAYORUNIQUE = aPAYORUNIQUE then
        始める
          結果 := 私;
          壊す;
        終わり;
    終わり;

    手順 TPayors.SortByName;
    変数
      fSort:TStringList;
      fParse:TStrings;
      I、Idx: 整数。
      fTempPayor:TPayors;
    始める
      fSort := TStringList.Create;
      fParse := TStringList.Create;
      fTempPayor.Items:= Self.Items;
      fSort.Sorted := True;
      試す
        for I := 0 to Count - 1 do
          fSort.Add(Items[I].LOCALNAME + #9 + IntToStr(I));
        アイテム := なし;
        for I := 0 to fSort.Count - 1 do
          始める
            cbs.utils.ParseDelimited(fParse,fSort[I],#9);
            Idx := StrToInt(fParse[1]);
            Add(fTempPayor.Items[Idx]);
          終わり;
      最後に
        fTempPayor.Free;
        fParse.Free;
        fSort.Free;
      終わり;
    終わり;

    関数 TPayors._pGetCount: 整数;
    始める
      結果:=長さ(アイテム);
    終わり;

    終わり。

4

1 に答える 1

6

あなたは(おそらく)文字列リストを二重に解放しています(少なくとも1つを解放することはありません)。問題は、「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;
于 2014-07-21T18:25:48.753 に答える