Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  15:04[Войти] | [Зарегистрироваться]
Ответ на вопрос № 63889

Вопросы с аналогичными сообщениями об ошибках:
  • Access violation at address ... (776)

    17-07-2008 15:50
    Что-то я сюда зачастил...

    Здравстуйте, жители королевства.
    У меня проблема при динамическом создании формы. Описываю:
    Раньше  форма создавалась стандартно:

    program Project1;
    uses
      Forms,
      Unit1 in 'Unit1.pas' {Form1},
      u_options in 'u_options.pas' {f_options};

    {$R *.res}

    begin
      Application.Initialize;
      Application.CreateForm(TForm1, Form1);
      //Application.CreateForm(Tf_options, f_options);
      Application.Run;
    end.

    Как видно, я закомментил создание формы и решил создавать ее динамически, в момент вызова:

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      if not Assigned(F_Options) then
        f_options:=Tf_options.Create(Application);
      f_options.show;
    end;


    В событие onCreate моей формы f_options прописан код:

    Caption      := LangPlug.Options.F_caption;
              TreeOptions.Items.Item[0].Text := LangPlug.Options.TreeOptionsMain;
              TreeOptions.Items.Item[1].Text := LangPlug.Options.TreeOptionsConnection;
              TreeOptions.Items.Item[2].Text := LangPlug.Options.TreeOptionsOther;

    На котором вылетате Access Violation... Что я делаю не так?

    [+] Добавить в избранные вопросы

    Отслеживать ответы на этот вопрос по RSS

    Ответы:


    Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
    Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

    18-07-2008 05:30 | Сообщение от автора вопроса
    NS, спасибо!

    18-07-2008 04:04 | Комментарий к предыдущим ответам
    Годится:)

    18-07-2008 03:50 | Комментарий к предыдущим ответам
    Что-ж, сойдёмся на том, что это зависит от того, с какой стороны на это смотреть :)

    18-07-2008 03:41
    Да нет, все-таки подменяет:) То есть магия заключатся в неявном вызове компилятором NewInstance при вызове конструктора как метода класса, а Application.CreateForm делает то-же самое, но явно, да еще вклинивая туда TComponent(Reference) := Instance. Так что все-таки - подменяет:)))

    18-07-2008 03:27 | Комментарий к предыдущим ответам
    >>> Application.CreateForm подменяет эту магию компилятора
    Только наверное не подменяет, а использует. Т.е. пользуется возможностью использовать конструктор и так и сяк.

    P.S.
    Ну и ссылочку тогда уж по теме: http://hallvards.blogspot.com/2008/01/tdm3-rise-and-fall-of-tobject.html

    18-07-2008 03:16
    Отличие двух вариантов в том, что в одном случае сперва выделяется память, а потом уже запускается конструктор, а в другом - что выделение памяти берёт на себя конструктор.

    Более строго говоря, метод Application.CreateForm вначале создает экземпляр объекта, потом присваивает переменной ссылку на него, и только после этого производит инициализацию объекта, чем по сути дела и занимается дельфийский конструктор, а настоящим конструктором является NewInstance, который и создает реально экземпляр объекта и производит его начальную инициализацию. А constructor было-бы, на мой взгляд, логичнее назвать Initialize, это бы точнее отразило его назначение.

    Возможно стоит упомянуть, что при вызове конструктора как метода класса имеет место т.н. "Compiler magic". Компилятор неявно вставляет сначала вызов NewInstance, а уже после этого вызывает сам конструктор, передав ему только-что созданный объект.

    А Application.CreateForm подменяет эту магию компилятора своим поведением с главной целью - присвоить переменной ссылку на новый объект до его инициализации.

    18-07-2008 02:42 | Сообщение от автора вопроса
    Александр Алексеев, большое вам спасибо за столь подробный и обстоятельный ответ! Очень признателен!

    18-07-2008 02:27
    Отличие двух вариантов в том, что в одном случае сперва выделяется память, а потом уже запускается конструктор, а в другом - что выделение памяти берёт на себя конструктор.

    1. Application.CreateForm(Tf_options, f_options);

    procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
    var
      Instance: TComponent;
    begin
      Instance := TComponent(InstanceClass.NewInstance); // В этот момент для объекта формы выделяется память
      TComponent(Reference) := Instance; // Теперь объект записывается в Instance, в нашем случае - в переменную f_options.

      // К этому момент f_options содержит форму, но она ещё не инициализирована

      if (FMainForm = nil) and (Instance is TForm) then
        SetCreatingMainForm(TControl(Instance));
      try
        try
          Instance.Create(Self); // Здесь вызывается конструктор, он инициализирует форму, создаёт компоненты и т.п.
          // Сразу после конструктора срабатывает AfterConstruction, который вызывает событие OnCreate. В Oncreate ваш код может оперировать с f_options, т.к. ссылка в неё была вписана выше.
        except
          TComponent(Reference) := nil;
          raise;
        end;
    ...



    2. f_options := Tf_options.Create(Application);

    Очевидно, что здесь сначала выполняется Tf_options.Create(Application), а затем - операция присвоения (наоборот нельзя - ведь тогда бы нечего было бы присваивать).

    Tf_options.Create(Application);


    Здесь вызывается конструктор, он выделяет память под объект (форму), инициализирует её, загружает компоненты и т.п.
    Сразу после конструктора вызывается AfterConstruction, он вызывает событие OnCreate. Ваш код не может обратиться к форме через f_options, т.к. сейчас она равна nil - ведь её же никто не инициализировал. Чтобы кто-то обратился к форме, мы должны явно передать ему ссылку, либо же вручную её вписать, например так:

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      f_options := Self;
      // ... другой код теперь может обратиться к форме через f_options
    end;



    f_options := {созданная форма}


    И только после выхода из AfterConstruction выполняется присваивание. Теперь f_options содержит объект формы и мы можем обратиться к форме через f_options.

    18-07-2008 02:15
    >>> пытпюсь их присвоить компонентам на форме
    Вот в этот момент у вас AV и есть.

    >>> А как быть в такой ситуации: в onCreate вызывается процедура, в коде которой идет обращение к f_options и данная процедура находится в другом юните?

    Например:

    procedure Tf_options.FormCreate(Sender: TObject);
    begin
      Load(Self);
    end;

    ...
    uses f_options;

    procedure Load(AForm: Tf_options);
    begin
      AForm.TreeOptions.Items.Item[0].Text:='test';
    end;



    Или:

    procedure Tf_options.FormCreate(Sender: TObject);
    begin
      Load(Self);
    end;

    ...
    uses f_options;

    procedure Load(AForm: TForm);
    begin
      if AForm is Tf_options then
      with Tf_options(AForm) do
      begin
        TreeOptions.Items.Item[0].Text:='test';
      end;
    end;



    (а вообще я бы сделал Load методом).

    18-07-2008 02:04
    NS, я просто хочу до конца разобраться, не использую при этом Application.CreateForm(Tf_options, f_options)

    18-07-2008 01:58 | Сообщение от автора вопроса
    Покажите, что такое TreeOptions и LangPlug?
    TreeOptions это TTreeView, а LangPlug- грубо говоря, массив со строковыми значения (я туда гружу строчки из файла, а потом,в момент создания формы, пытпюсь их присвоить компонентам на форме).

    Мне кажется, что какой-то объект не создан у Вас, но используется в OnCreate();
    Попробуйте поставить там ShowMessage(); и посмотреть что выйдет.

    У меня вообще ощущение, что создается только форма, потом вызывается onCreate, а потом уже создаются компоненты на форме%)

    TreeOptions.Items.Item[] - а сами Item-ы созданы?
    да

    то в OnCreate формы имеет место обращение к самому себе не через Self, а через переменную f_optionsтак и есть... А как быть в такой ситуации: в onCreate вызывается процедура, в коде которой идет обращение к f_options и данная процедура находится в другом юните?
    Типа:

    procedure Tf_options.FormCreate(Sender: TObject);
    begin
      Load;
    end;

    ...
    uses f_options;

    procedure Load;
    begin
      f_options.TreeOptions.Items.Item[0].Text:='test';
    end;



    18-07-2008 00:31
    Если при AutoCreate работало, а после закомментирования перестало, то в OnCreate формы имеет место обращение к самому себе не через Self, а через переменную f_options. Если это так, то при таком коде

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      if not Assigned(F_Options) then
        Application.CreateForm(Tf_options, f_options);
      f_options.show;
    end;


    AV должно исчезнуть. Но лучше объектам не обращаться к самим себе через внешнюю переменную.

    18-07-2008 00:01
    TreeOptions.Items.Item[] - а сами Item-ы созданы?

    17-07-2008 23:43
    P.S. естесственно закомментировать это

    Caption      := LangPlug.Options.F_caption;
              TreeOptions.Items.Item[0].Text := LangPlug.Options.TreeOptionsMain;
              TreeOptions.Items.Item[1].Text := LangPlug.Options.TreeOptionsConnection;
              TreeOptions.Items.Item[2].Text := LangPlug.Options.TreeOptionsOther;


    17-07-2008 23:42
    Странно, сделал -- все нонрмально работает.
    Мне кажется, что какой-то объект не создан у Вас, но используется в OnCreate();
    Попробуйте поставить там ShowMessage(); и посмотреть что выйдет.

    17-07-2008 23:41 | Вопрос к автору: запрос дополнительной информации
    Покажите, что такое TreeOptions и LangPlug?

    17-07-2008 22:26
    Ну так поставьте в OnCreate точку останова, и медленно пройдите отладчиком, контролируя все переменные и заходя во все функции. Где то увидите обращение к переменной, равной nil.

    Добавьте свое cообщение

    Вашe имя:  [Войти]
    Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
    контрольный вопрос:
    Жил-был у бабушки серенький КТО?
    в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
    Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
    Тип сообщения:
    Текст:
    Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Вопросы с аналогичными сообщениями об ошибках:
  • Access violation at address ... (776)


    Страница избранных вопросов Круглого стола.
  •   
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования