Здравствуйте, 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?
я думаю этот список легко дополнить... у тебя какой вариант?