Re: Снова this в конструкторе
От: Caracrist https://1pwd.org/
Дата: 01.03.12 19:47
Оценка: 2 (1) +1
Здравствуйте, found, Вы писали:

F>Здравствуйте.


F>Читал в разных местах, что с одной стороны использование this в конструкторе — нормальная практика, с другой стороны нет.

F>Опишу задачу упрощенно: при конструировании объекта создать, связанный с ним поток, использующий некоторые поля объекта.
F>Пример:

F>
F>struct Foo
F>{
F>  Foo() : data(0)
F>  {
F>    CreateThread(..., Starter, this, ...);
F>  }

F>  static int Starter(void* obj)
F>  {
F>    static_cast<Foo*>(obj)->run();
F>  }

F>  void run()
F>  {
F>    m_Data++;
F>  }

F>  int m_Data;
F>}
F>

В данном примере проблемы нет.

F>Можно ли поступать подобным образом? Передавать this во внешнюю функцию, которая вызывает статическую функцию с этим параметром, далее относительно него запускать функцию член.

Если от этого класса не наследуются, и это последний конструктор то из него можно всё запускать.

F>Реальная задача:

F>Внутри объекта хранится объект — событие и ссылка на внешнее событие. В конструкторе необходимо запустить поток, в котором сигнализировать событием объекта и остановиться в ожидании внешнего события.
F>В итоге происходит следующая последовательность действий:
F>1. В конструкторе создается объект событие
F>2. В конструкторе создается поток, приемом описанным выше
F>3. Внутри функции потока событие объекта устанавливается в сигнальное состояние
F>4. Функция потока останавливается в ожидании внешнего события

F>Как правило, приведенная схема работает. Но когда потоков становится действительно много, иногда возникает ситуация, когда пункт 3 алгоритма приводит к ошибке обращения к памяти, при чем с помощью отладчика, удалось выяснить, что неверен не только объект внутреннего события, но и все остальные поля класса, из чего я делаю вывод, что неверен указатель this, относительно которого вызывается функция член класса.

Вот список возможных проблем:
* Время жизни объекта короче времени жизни потока. От сюда: кирдык.
* Вызываемая функция не потокобезопасна(как в примере: ++ там не защищён)
* Вызов виртуальной функции из потока, равно как и вызов виртуальной функции из конструктора = UB
* dynamic_cast из потока, равно как и из конструктора = UB
* исключение брошенное из дальнейшего кода в конструторе приведёт в конечном счёте к инвалидации объекта
* исключение при инициализации следующего из массива объекта Foo oops[3]; приведёт в конечном счёте к инвалидации объекта


F>В чем может быть реальная проблема в пункте 3?


я думаю этот список легко дополнить... у тебя какой вариант?
~~~~~
~lol~~
~~~ Single Password Solution
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.