На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Обязательно выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.

Этот раздел предназначен для вопросов, посвященных разработке компонентов, а также для тестирования собственных бесплатных компонентов с открытым исходным кодом.

Здесь запрещается:
1. Размещать ссылки на какие-либо коммерческие компоненты, реализующие требуемую функциональность.
2. Обсуждать и тестировать коммерческие компоненты или компоненты с закрытым кодом.
3. Давать ссылки на сайты с исходным кодом компонентов. Все тестируемые исходные коды должы быть размещены на сайте ИСХОДНИКИ.RU.
Модераторы: Rouse_, DimaBr
  
> Неверное обращение к памяти при закрытии объекта в деструкторе. , Неверное обращение к памяти при закрытии объекта в деструкторе.
    Добрый день!

    Создан дочерний компонент по схеме:

    ExpandedWrap disabled
      unit MyChildComponent;
       
      interface
       
      uses
        Windows, Messages, SysUtils, Variants, Classes;
       
      type
        TMyChildComponent = class(TComponent)
        private
          { Private declarations }
          FParentComponent : TMyComponent;
        protected
          { Protected declarations }
        public
          { Public declarations }
          constructor Create(AOwner : TComponent); override;
          destructor Destroy; override;
        published
          { Published declarations }
          property ParentComponent : TMyComponent read FParentComponent write FParentComponent;
        end;
       
        procedure Register;
       
      implementation
       
      constructor TMyChildComponent.Create(AOwner: TComponent);
      begin
        inherited Create(AOwner);
        FParentComponent := TMyComponent.Create(Self);
      end;
       
      destructor TMyChildComponent.Destroy;
      begin
        if not Assigned(FParentComponent) then
          FreeAndNil(FParentComponent);
        inherited;
      end;
       
      procedure Register;
      begin
        RegisterComponents('test',  [TMyChildComponent]);
      end;
       
      end.


    Свойство ParentComponent в виде выпадающего списка находит родительский компонент TMyComponent, из которого читаются некоторые параметры в дочерний компонент TMyChildComponent. Компилируются компоненты TMyChildComponent и TMyComponent нормально, на форме в realtime TMyChildComponent прекрасно видит TMyComponent. Далее если положить эти компоненты на форму в новом проекте, запустить его, закрыть и попытаться закрыть сам проект - выдается ошибка:

    ---------------------------
    Error
    ---------------------------
    Invalid pointer operation.
    ---------------------------
    OK Details >>
    ---------------------------

    Эта ошибка связана с деструктором. Если удалить конструкцию "if not Assigned(FMyComponent) then", то ошибка аналогичного типа выдается не при закрытии проекта вцелом, а уже при закрытии самой формы. Подскажите как это можно исправить? Может я что-то в деструкторе неверно прописал?

    Спасибо всем за помощь.
    Сообщение отредактировано: SkAndriy -
      Наследники TComponent сами убивают своих вложенных собратьев.

      Чтобы избежать такой ошибки, надо делать:
      ExpandedWrap disabled
        FParentComponent := TMyComponent.Create(nil);
        Приведенные конструктор и деструктор просто не нужны.
          Спасибо. проблема решена.
            Цитата SkAndriy @
            Спасибо. проблема решена.

            По совету yavfast?
            Если да, то вы получили новую: утечку памяти.
            Для того чтобы убедиться в этом в тестововм проекте присвойте глобальной переменной ReportMemoryLeaksOnShutDown значение true. Сделать это удобно например в секции initialization модуля главной формы, а еще лучше в файле проекта сразу после слова begin.
            Тогда менеджер памяти при выходе из программы уведомит вас с помощью диалогового окошка об имеющихся утечках если таковые на самом деле есть. Если нет, то никакого окошка не уидите.
              Сделал как Вы советовали


              В

              ExpandedWrap disabled
                  public
                    { Public declarations }
                  end;
                 
                var
                  Form1: TForm1;
                  ReportMemoryLeaksOnShutDown : Boolean;
                 
                implementation
                 
                {$R *.dfm}


              объявил глобальную переменную

              в модуле проекта ее после begin прописал:

              ExpandedWrap disabled
                program Project1;
                 
                uses
                  Forms,
                  Unit1 in 'Unit1.pas' {Form1};
                 
                {$R *.res}
                 
                begin
                  ReportMemoryLeaksOnShutDown := True;
                  Application.Initialize;
                  Application.CreateForm(TForm1, Form1);
                  Application.Run;
                end.


              Никаких сообщений не получил. Все правильно прописал?

              Спасибо
                Цитата SkAndriy @
                объявил глобальную переменную

                Нет, объявлять ничего не надо было: она уже объявлена в модуле System. Можете даже это уточнить в коде явно.
                ExpandedWrap disabled
                  program Project1;
                   
                  uses
                    Forms,
                    Unit1 in 'Unit1.pas' {Form1};
                   
                  {$R *.res}
                   
                  begin
                    System.ReportMemoryLeaksOnShutdown := true;
                   
                    Application.Initialize;
                    Application.MainFormOnTaskbar := True;
                    Application.CreateForm(TForm1, Form1);
                    Application.Run;
                  end.

                Ваша вновь объявленная переменная конечно скрыла оригинальную, которую анализирует менеджер памяти. Соответственно никаких сообщений вы таким образом не получите даже при утечках.

                Объявление из модуля формы лучше убрать даже при указании модуля явно.
                  И как разобраться в полученном перечне? По компоненту (его типам) от 23 до 84 байт. Что это означает? И как тогда поступить с моей проблемой, чобы не было утечки памяти?
                  Сообщение отредактировано: SkAndriy -
                    Цитата SkAndriy @
                    И как разобраться в полученном перечне?

                    Ого, так там еще и целый перечень!
                    Из того, что показано в первом посте должно быть только TMyComponent x количество набросанный TMyChildComponent'ов c переустановленным свойством ParentComponent. Лечится это удалением приведенных конструктора и деструктора (если это полное их содержимое и нет ничего что вы не стали здесь приводить как не относящееся к проблеме), так они только вредят.

                    Если что-то еще есть в перечне, так по имени типа ищите где создаются соответствующие объекты и не освобождаются.
                      Для справки две трети этого списка - это модули бренда программирования Делфи 2010. А мои модули имеют скромные несколько десятков байт всего.
                      Если Вы пишете, что конструкторы и деструкторы не нужны, то как же тогда создавать компоненты. Это что-то новое. Поясните свою мысль, может действительно я отстал от реальной жизни и компоненты уже создаются без конструкторов и деструкторов. Спасибо.
                      Сообщение отредактировано: SkAndriy -
                        Цитата SkAndriy @
                        Если Вы пишете, что конструкторы и деструкторы не нужны, то ка же тогда создавать компоненты. Это что-то новое. Поясните сволю мысль может действительно я отстал от реальной жизни и компоненты уже создаются без конструкторов и деструкторов.

                        Ничего нового здесь нет. Конструктор и деструктор будут использованы унаследованные и совершенно нет никакой необходимости их заменять новыми с единственным полезным действием - вызовом унаследованных версий.
                          Цитата SkAndriy @
                          Если Вы пишете, что конструкторы и деструкторы не нужны, то ка же тогда создавать компоненты. Это что-то новое

                          Не нужно переопределять конструкторы\деструкторы, если они не выполняют никаких полезных действий по сравнению с наследуемыми (inherited). Зачем ты в #1 в конструкторе создаешь некий безымянный FParentComponent, который затем может "10 раз" переустановиться в инспекторе - совершенно не понятно. Аналогично и в деструкторе незачем удалять дочерний компонент, т.к. он сам удалится в inherited Destroy
                            Спасибо, попробую.
                              PS:
                              Цитата leo @
                              в деструкторе незачем удалять дочерний компонент, т.к. он сам удалится в inherited Destroy

                              А если это не дочерний, а некий "родительский", назначаемый в инспекторе, то тем более - нельзя удалять то, "что тебе не принадлежит"
                              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                              0 пользователей:


                              Рейтинг@Mail.ru
                              [ Script execution time: 0,0353 ]   [ 16 queries used ]   [ Generated: 19.04.24, 00:50 GMT ]