Delphi XE3 Invalid Pointer при попытке освободить 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(Pointer(Self)); в процедуре TObject.FreeInstance в системном блоке выполните следующие действия:

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

Если я не освобожу элемент данных TStringList, у меня будет утечка памяти в приложении.

Есть ли возможность конфигурации, которую мне нужно установить? Я выполнил поиск в Google и не нашел ничего, что объясняет, что я делаю неправильно, кроме одной из трех возможностей:

  • Он был выделен другим менеджером памяти.
  • Он уже был освобожден однажды.
  • Он никогда ничего не выделял.

Если я попытаюсь... кроме... Я могу обойти проблему, но я предпочитаю не делать этого.

Кстати, у меня есть другой TStringList в другом модуле, и я создаю и FreeAndNil, и я не получаю никакой ошибки.

Вот весь источник:

    блок PayorDataMgr; интерфейс использует SysUtils, Classes, Dialogs, NativeXML, adscnnct, DB, adsdata, adsfunc, adstable, ace, cbs.drm, cbs.utils, cbs.LogFiles;

    const
      POLICY_TYPES: массив [1..3] из string = ("Первичный", "Вторичный", "Третичный"); Тип TPayorRecord = Запись ASSIGNBENEFITS: Boolean; АВТОРИЗАЦИЯ: логическое; BATCHBILL: логическое значение;
        CLAIMMAX: целое число; ПРОДОЛЖЕНИЕ: TDateTime; DISPENSEUPDATE: логическое значение;
        EHRSIGNOFF: логическое значение; EMCDEST: Строка; ФОРМА: Строка;
        GOVASSIGN: логическое значение;
        HIDE: Boolean;
        IGRPUNIQUE: целое число;
        LEGACYPLAN: Строка;
        LEGACYTYPE: String;
        LOCALATTN: Строка; МЕСТНОСТЬ: строка; МЕСТНОЕ ИМЯ: Строка; ЛОКАЛЬФОН: Строка; LOCALSTATE: String; LOCALSTREET: Строка; МЕСТНЫЙ ЗНАК: Строка; MASTERATTN: Строка; МАСТЕРСТВО: Строка; MASTERNAME: String; МАСТЕРФОН: Струна; MASTERSTATE: строка; MASTERSTREET: Строка; МАСТЕРЗИП: Струнный;
        MEDIGAPCODE: String;
        MEDIGAPPAYOR: Boolean;
        MEDPLANGUID: Строка; ИЗМЕНЕНО: TDateTime; NEICCODE: Строка; NEICTYPESTDC: целое число; ВЛАДЕЛЕЦ: Строка;
        PAYORGUID: Строка;
        PAYORSUBTYPESTDC: целое число; PAYORTYPESTDC: целое число;
        PAYORUNIQUE: целое число; PAYPERCENT: целое число; RTCODE: Строка;
        SRXPLANGUID: String;
        STATEFILTER: String; процедура Clear; Конец; TPayors = Запись закрытой функции _pGetCount: Integer;
      public
        Items: Массив TPayorRecord; процедура добавления (const aItem: TPayorRecord); функция CarriersList: TStrings; процедура бесплатная;
        function GetPayorGuid(const aPAYORUNIQUE:Integer):String;
        function IndexOfIgrpUnique(Const aIGRPUNIQUE:Integer):Integer;
        function IndexOfPayorUnique(Const aPAYORUNIQUE:Integer):Integer; процедура SortByName; Свойство Count:Integer Read _pGetCount; Конец; TPayorDM = класс (TDataModule)
        CommonConnection: TAdsConnection;
        T_Payor: TAdsTable;
        Q_Payor: TAdsQuery; процедура DataModuleDestroy (Отправитель: TObject); процедура DataModuleCreate (Отправитель: TObject); частный FPayorDRM: TDRM;
        FSQL: TStringList;
        function _LoadRecordFromTable:TPayorRecord;
        function _newIDSTRING(const aFormat:String='F'):String; Процедура {частные объявления} _pSetConnectionHandle(const Value: Integer); процедура _pSetErrorMessage(const Value: String); процедура _psetSQL(постоянное значение: TStringList); Свойство { Private properties } ErrorMessage:String Write _pSetErrorMessage; открытая функция AddPayor(var aPAYORRECORD:TPAYORRECORD):Boolean; функция ExecuteScript(const aTo,aFrom:string):Boolean;
        function FindPayor(const aPAYORGUID:String):Boolean; перегрузка;
        function FindPayor(const aPAYORUNIQUE:Integer):Boolean; перегрузка;
        function GetPayorData:TDRM;
        function GetRecordCount(const aData:String):Integer; функция LoadCarriers(const aHide:boolean = False):TPayors; функция LoadPayor: TPayorRecord; функция OpenTable:Boolean;
        function UpdateFromXML(const aPayorNode:TXMLNode): логический; Свойство {Публичные объявления} ConnectionHandle:Integer Write _pSetConnectionHandle; свойство DynamicPayorFields: TDRM Чтение FPayorDRM; свойство SQL: TStringList Чтение FSQL Запись _psetSQL; конец; вар PayorDM: TPayorDM; реализация {$R *.dfm} функции TPayorDM.AddPayor(var aPAYORRECORD: TPAYORRECORD): Boolean;
    begin
      Result:= False; если IsNull (aPAYORRECORD.LOCALNAME), то Exit;
      {Создать уникальные}

      {Добавить запись}, если не T_Payor.Active, то если не OpenTable, то Exit; с T_Payor попробуйте вставить;
        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, действительно начинайте ErrorMessage:= 'AddPayor: ERRORCODE: ' + IntToStr(e.ACEErrorCode) +
          ' ERROR: ' + e.Message; конец; конец; конец; процедура TPayorDM.DataModuleCreate (Отправитель: TObject); начать FPayorDRM:= TDRM.Create;
      FSQL:= TStringList.Create; { FSQL Created }
   end; процедура TPayorDM.DataModuleDestroy (Отправитель: TObject); начать пробовать FSQL.Free; { FSQL Destroy - обойти, чтобы заставить модуль работать без ошибок}, кроме end; если T_Payor.Active, то T_Payor.Close; FreeAndNil (FPayorDRM); конец; function TPayorDM.ExecuteScript (const aTo, aFrom: string): Boolean; begin Result: = False; если FSQL.Count = 0, выход; с Q_Payor попробуйте если Active, то Close;
        SQL:= FSQL;
        ParamByName('to').Text:= aTo;
        ParambyName('from').Text:= aFrom;
        ExecSQL; если активен, то закрыть; Результат: = Истина; за исключением E: EADSDatabaseError, действительно начинайте ErrorMessage:= 'ExecuteScript: ERRORCODE: ' + IntToStr(e.ACEErrorCode) +
          ' ERROR: ' + e.Message + ' SQL: ' + Q_Payor.SQL.Text; конец; конец; конец;

    function TPayorDM.FindPayor(const aPAYORUNIQUE: Integer): Boolean;
    begin
      T_Payor.IndexName:= 'PAYORUNIQUE'; Результат:= T_Payor.FindKey([aPAYORUNIQUE]); конец;

    function TPayorDM.FindPayor(const aPAYORGUID: String): Boolean;
    begin
      T_Payor.IndexName:= 'PAYORGUID'; Результат:= T_Payor.FindKey([aPAYORGUID]); конец;

    function TPayorDM.GetPayorData: TDRM; начинать, если FPayorDRM.Count = 0, тогда FPayorDRM.BuildDRMList(T_Payor); Результат: = FPayorDRM; конец;


    function TPayorDM.GetRecordCount(const aData:string): целое число; начало Результат:= 0; если FSQL.Count = 0, выход; с Q_Payor попробуйте если Active, то Close;
        SQL:= FSQL;
        ParamByName('data').AsString:= aData; Открыто; Результат: = RecordCount; Близко; за исключением E: EADSDatabaseError, действительно начинайте ErrorMessage:= 'GetRecordCount: ERRORCODE: ' + IntToStr(e.ACEErrorCode) +
          ' ERROR: ' + e.Message; конец; конец; конец; Функция TPayorDM.LoadCarriers(const aHide: boolean): TPayors; начать OpenTable;
      Result.Free; с T_Payor начинайте сначала; хотя не EOF, начинайте, если T_Payor.FieldByName('HIDE').AsBoolean = aHide then
            Result.Add(_LoadRecordFromTable); Следующий; конец; Первый; Result.SortByName; конец; конец; функция TPayorDM.LoadPayor: TPayorRecord; начать Result.Clear; попробуйте если не T_Payor.active, тогда выходите; если T_Payor.RecNo = 0, тогда выход; Результат:= _LoadRecordFromTable; за исключением E: EADSDatabaseError, действительно начинайте ErrorMessage:= 'LoadPayor: ERRORCODE: ' + IntToStr(e.ACEErrorCode) +
          ' ERROR: ' + e.Message; конец; конец; конец;

    function TPayorDM.OpenTable: Boolean;
    begin
      Result:= False; с T_Payor попробуйте, если не активен, то Open;
        FPayorDRM.BuildDRMList(T_Payor);
        FPayorDRM.LoadValues ​​(T_Payor); { test }
        FPayorDRM.ExportDRMList; { test } Результат: = True; за исключением E: EADSDatabaseError, действительно начинайте ErrorMessage:= 'OpenTable: ERRORCODE: ' + IntToStr(e.ACEErrorCode) +
          ' ERROR: ' + e.Message; конец; конец; конец;

    function TPayorDM.UpdateFromXML(const aPayorNode: TXMLNode): логический;
    var
      fKeyData:TXMLNode;
      IDX,fPAYORUNIQUE:Integer;
    begin
      Result:= False; если не назначено (aPayorNode), то Exit; попробуйте, если 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:= Now;
          FPayorDRM.AddRecord(T_Payor) и конец другого начала FPayorDRM.FieldByName('MODIFIED').AsDate:= Now;
          FPayorDRM.UpdateRecord(T_Payor); конец; кроме случаев e: исключение, начинайте ErrorMessage:= 'UpdateFromXML: ОШИБКА:' + e.Message; конец; конец; конец;

    function TPayorDM._LoadRecordFromTable: TPayorRecord; начинаются с T_Payor и начинаются 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;
    begin
      Result:= ''; попробуй с Q_Payor сделай попробуй SQL.Clear;
          SQL.Add('ВЫБЕРИТЕ NEWIDSTRING( "' + aFormat + '") как GUID FROM system.iota'); Открыто; Результат:= FieldByName('GUID').AsString; Близко; кроме E: EADSDatabaseError, действительно начинайте ErrorMessage:= '_newIDSTRING: ERRORCODE: ' + IntToStr(e.ACEErrorCode) +
            ' ERROR: ' + e.Message; конец; конец; наконец-то конец; конец; процедура TPayorDM._pSetConnectionHandle(постоянное значение: целое число); начинать, если T_Payor.Active тогда T_Payor.Close;
      CommonConnection.SetHandle(значение); Открытый стол; конец; процедура TPayorDM._pSetErrorMessage(const Value: String);
    begin
      WriteError('[TPayorDM]' + Value,LogFilename); конец; процедура TPayorDM._psetSQL(постоянное значение: TStringList); начать FSQL: = значение; конец;

    { TPayorRecord } процедура TPayorRecord.Clear; начать PAYORUNIQUE:= 0;
      PAYORGUID:= '';
      MASTERNAME:= '';
      MASTERSTREET:= ''; МАСТЕРСТВО:= '';
      MASTERSTATE:= '';
      PAYORTYPESTDC:= 0;
      MASTERZIP:= '';
      MASTERATTN:= ''; МАСТЕРФОН:= '';
      NEICCODE:= '';
      RTCODE:= '';
      STATEFILTER:= '';
      NEICTYPESTDC:= 0;
      PAYORSUBTYPESTDC:= 0; ВЛАДЕЛЕЦ:= '';
      HIDE:= Ложь;
      IGRPUNIQUE:= 0; ФОРМА:= '';
      GOVASSIGN:= Ложь;
      CLAIMMAX:= 0;
      MEDIGAPCODE:= '';
      EMCDEST:= ''; НАЗНАЧЕНИЕ ПРЕИМУЩЕСТВ:= False;
      BATCHBILL:= Ложь;
      MEDIGAPPAYOR:= Ложь;
      MEDPLANGUID:= '';
      SRXPLANGUID:= '';
      PAYPERCENT:= 0; ЛОКАЛЬНОЕ ИМЯ: = ''; LOCALSTREET: = ''; МЕСТНОСТЬ:= '';
      LOCALSTATE:= '';
      LOCALZIP:= '';
      LOCALATTN:= ''; ЛОКАЛЬФОН: = '';
        EHRSIGNOFF: = Ложь; ПРОДОЛЖЕНИЕ:= 0; ИЗМЕНЕНО:= 0;
      LEGACYPLAN:= '';
      LEGACYTYPE:= ''; РАЗРЕШИТЬ: = Ложь; DISPENSEUPDATE: = Ложь; конец; Процедура { TPayors } TPayors.Add(const aItem: TPayorRecord);
    begin
      SetLength(Items,Count + 1);
      Items[Count - 1]:= aItem; конец; функция TPayors.CarriersList: TStrings;
    var
      I: целое число;
    begin
      Result:= TStringList.Create;
      Result.Clear; Сортировать по имени; попробуйте для I:= 0 для подсчета - 1 для Result.Add(Items[I].LOCALNAME); наконец-то конец; конец; процедура TPayors.Free; начало элементов: = ноль; конец;

    function TPayors.GetPayorGuid(const aPAYORUNIQUE: Integer): String;
    var
      Idx:Integer;
    begin
      Result:= '';
      Idx:= IndexOfPayorUnique(aPAYORUNIQUE); если нет (Idx = -1), то Результат:= Items[Idx].PAYORGUID; конец; функция TPayors.IndexOfIgrpUnique(const aIGRPUNIQUE: Integer): Integer;
    var
      I: целое число; начало Результат:= -1; для I:= 0 до счета - 1 делать, если элементы [I].IGRPUNIQUE = aIGRPUNIQUE затем начинаются Результат: = I; Перерыв; конец; конец;

    function TPayors.IndexOfPayorUnique(const aPAYORUNIQUE: Integer): Integer;
    var
      I: целое число; начало Результат:= -1; для I:= 0 для подсчета - 1 делать, если элементы [I].PAYORUNIQUE = aPAYORUNIQUE затем начинают Результат: = I; Перерыв; конец; конец; процедура 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; попробуйте для I:= 0 для подсчета - 1 для fSort.Add(Items[I].LOCALNAME + #9 + IntToStr(I)); Предметы: = ноль; для I: от = 0 до fSort.Count - 1 начинается cbs.utils.ParseDelimited(fParse,fSort[I],#9);
            Idx:= StrToInt(fParse[1]); Добавить (fTempPayor.Items[IDX]); конец; наконец, fTempPayor.Free;
        fParse.Free;
        fSort.Free; конец; конец;

    function TPayors._pGetCount: Integer; начало Результат: = длина (элементы); конец; конец.

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;
Другие вопросы по тегам