当前位置: 首页 > 知识库问答 >
问题:

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

蔺敏达
2023-03-14

我正在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.

共有1个答案

仲孙铭
2023-03-14

您(很可能)正在双重释放一个字符串列表(并且永远不会释放至少一个)。问题出在您的“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指针。 在调用函数之前,我不应该知道我使用