_beginthreadex и деструкторы
От: VNG Беларусь https://organicmaps.app/
Дата: 05.10.04 10:45
Оценка:
Допустим есть код:

    unsigned int _stdcall ThreadLoading(void* p)
    {
        CSomeClass someObject;

        _endthreadex(0);
        return 0;
    }
    
    int main()
    {
        unsigned int nID;
        HANDLE hThread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, &ThreadLoading, NULL, 0, &nID));
        
        ::WaitForSingleObject(hThread, INFINITE);
        ::CloseHandle(hThread);
    }


Так вот какая проблема. Когда срабатывает _endthreadex(0), функция ожидания ::WaitForSingleObject(hThread, INFINITE) возвращается и соответсвенно следующей вызывается ::CloseHandle(hThread). В итоге имеем — деструктор объекта someObject не вызывается.

Что я делаю не так

Работаю с MSVC++7.1 и CRT, которая идет с ним же.

2Moderator. Просьба не отсылать в WinAPI или средства разработки.
... << RSDN@Home 1.1.3 beta 1 >>
Re: _beginthreadex и деструкторы
От: AlexBS Украина  
Дата: 05.10.04 10:54
Оценка:
Здравствуйте, VNG, Вы писали:


VNG>Так вот какая проблема. Когда срабатывает _endthreadex(0), функция ожидания ::WaitForSingleObject(hThread, INFINITE) возвращается и соответсвенно следующей вызывается ::CloseHandle(hThread). В итоге имеем — деструктор объекта someObject не вызывается.



_endthreadex завершает выполнение потока в момент ее вызова, а объект находиться в стеке.
В вашем примере вызов _endthreadex стоит убрать, т.к. поток завершиться сам собой при выходе из функции.
Re[2]: _beginthreadex и деструкторы
От: VNG Беларусь https://organicmaps.app/
Дата: 05.10.04 10:59
Оценка:
Здравствуйте, AlexBS, Вы писали:

ABS>В вашем примере вызов _endthreadex стоит убрать, т.к. поток завершиться сам собой при выходе из функции.


Будет ли это кошерно? В MSDN по-моему написано, что обязательно надо вызывать _endthreadex, если начинался поток с _beginthreadex.
... << RSDN@Home 1.1.3 beta 1 >>
Re[2]: _beginthreadex и деструкторы
От: SchweinDeBurg Россия http://zarezky.spb.ru/
Дата: 05.10.04 11:00
Оценка: +1 -1
Здравствуйте, AlexBS, Вы писали:

ABS>_endthreadex завершает выполнение потока в момент ее вызова, а объект находиться в стеке.

ABS>В вашем примере вызов _endthreadex стоит убрать, т.к. поток завершиться сам собой при выходе из функции.

Или вызвать деструктор(ы) явно непосредственно перед вызовом _endthreadex():

unsigned int _stdcall ThreadLoading(void* p)
    {
        CSomeClass someObject;

        someObject.~CSomeClass();
        _endthreadex(0);
        return 0;
    }
- Искренне ваш, Поросенок Пафнутий ~ ICQ#116846877
In Windows, there’s always a catch… © Paul DiLascia
Re: _beginthreadex и деструкторы
От: SiGMan / iO UpG Южная Корея www.ioupg.com
Дата: 05.10.04 11:00
Оценка: 2 (1) +1
Здравствуйте, VNG, Вы писали:


VNG>Что я делаю не так


Как вариант:

  unsigned int _stdcall ThreadLoading(void* p)
  {
      {
        CSomeClass someObject;
      }
     _endthreadex(0);
     return 0;
  }
io /l、 
゙(゚、 。 7
 l、゙ ~ヽ
 じしf_, )ノ
Re[3]: _beginthreadex и деструкторы
От: AlexBS Украина  
Дата: 05.10.04 11:02
Оценка: 8 (2) +1
Здравствуйте, VNG, Вы писали:

VNG>Здравствуйте, AlexBS, Вы писали:


ABS>>В вашем примере вызов _endthreadex стоит убрать, т.к. поток завершиться сам собой при выходе из функции.


VNG>Будет ли это кошерно? В MSDN по-моему написано, что обязательно надо вызывать _endthreadex, если начинался поток с _beginthreadex.



    You can call _endthread or _endthreadex explicitly to terminate a thread;
    however, _endthread or _endthreadex is called automatically when the thread
    returns from the routine passed as a parameter.
Re[3]: _beginthreadex и деструкторы
От: SchweinDeBurg Россия http://zarezky.spb.ru/
Дата: 05.10.04 11:04
Оценка: 1 (1)
Здравствуйте, VNG, Вы писали:

VNG>Будет ли это кошерно? В MSDN по-моему написано, что обязательно надо вызывать _endthreadex, если начинался поток с _beginthreadex.


ИМХО комментарий в MSDN звучит достаточно двусмысленно: с одной стороны

You can call _endthread or _endthreadex explicitly to terminate a thread; however, _endthread or _endthreadex is called automatically when the thread returns from the routine passed as a parameter to _beginthread or _beginthreadex.


но тут же следует "подозрительное"

Terminating a thread with a call to endthread or _endthreadex helps to ensure proper recovery of resources allocated for the thread.

- Искренне ваш, Поросенок Пафнутий ~ ICQ#116846877
In Windows, there’s always a catch… © Paul DiLascia
Re[4]: _beginthreadex и деструкторы
От: achp  
Дата: 05.10.04 12:13
Оценка: +1
Здравствуйте, SchweinDeBurg, Вы писали:

SDB>но тут же следует "подозрительное"


SDB>

SDB>Terminating a thread with a call to endthread or _endthreadex helps to ensure proper recovery of resources allocated for the thread.


Это в равной степени относится как к явному, так и к неявному вызову _endthreadex().

А противопоставление здесь может идти

а) с выходом из потока, использующего функции БВИ Си и/или созданного посредством вызова _beginthreadex(), при помощи прямого вызова ExitThread();
б) со свирепым убийством потока посредством TerminateThread().
Я кончил, джентльмены, мне остается только поблагодарить вас за внимание.
Re[5]: _beginthreadex и деструкторы
От: SchweinDeBurg Россия http://zarezky.spb.ru/
Дата: 05.10.04 12:26
Оценка: -3
Здравствуйте, achp, Вы писали:

SDB>>

SDB>>Terminating a thread with a call to endthread or _endthreadex helps to ensure proper recovery of resources allocated for the thread.


A>Это в равной степени относится как к явному, так и к неявному вызову _endthreadex().


Дай то Бог! Но поскольку "даже у параноиков могут быть враги" ( (с) Гувер ), япредпочитаю явный вызов (с предшествующим явным вызовом деструкторов локальных объектов).
- Искренне ваш, Поросенок Пафнутий ~ ICQ#116846877
In Windows, there’s always a catch… © Paul DiLascia
Re[3]: _beginthreadex и деструкторы
От: Аноним  
Дата: 05.10.04 14:27
Оценка:
Здравствуйте, VNG, Вы писали:

VNG>Здравствуйте, AlexBS, Вы писали:


ABS>>В вашем примере вызов _endthreadex стоит убрать, т.к. поток завершиться сам собой при выходе из функции.


VNG>Будет ли это кошерно? В MSDN по-моему написано, что обязательно надо вызывать _endthreadex, если начинался поток с _beginthreadex.


А если исходники _beginthreadex посмотреть?
Re[6]: _beginthreadex и деструкторы
От: Аноним  
Дата: 05.10.04 14:30
Оценка:
Здравствуйте, SchweinDeBurg, Вы писали:

....

SDB>япредпочитаю явный вызов (с предшествующим явным вызовом деструкторов локальных объектов).


Зачем???
Или лень исходники посмотреть?
Re[4]: _beginthreadex и деструкторы
От: achp  
Дата: 05.10.04 15:13
Оценка: +2
Здравствуйте, <Аноним>, Вы писали:

А>А если исходники _beginthreadex посмотреть?


Это может дать представление о том, "как оно устроено сейчас". Но если играть по правилам — нужно в первую очередь смотреть, что написано в MSDN. Это более веская гарантия правильности кодирования.
Я кончил, джентльмены, мне остается только поблагодарить вас за внимание.
Re[4]: _beginthreadex и деструкторы
От: Шахтер Интернет  
Дата: 05.10.04 19:41
Оценка: +3
Здравствуйте, SchweinDeBurg, Вы писали:

SDB>Здравствуйте, VNG, Вы писали:


VNG>>Будет ли это кошерно? В MSDN по-моему написано, что обязательно надо вызывать _endthreadex, если начинался поток с _beginthreadex.


SDB>ИМХО комментарий в MSDN звучит достаточно двусмысленно: с одной стороны


SDB>

SDB>You can call _endthread or _endthreadex explicitly to terminate a thread; however, _endthread or _endthreadex is called automatically when the thread returns from the routine passed as a parameter to _beginthread or _beginthreadex.


SDB>но тут же следует "подозрительное"


SDB>

SDB>Terminating a thread with a call to endthread or _endthreadex helps to ensure proper recovery of resources allocated for the thread.


Здесь имеется ввиду, что поток не стоит убивать апишными функциями, поскольку при этом не гарантируется очистка ресурсов, захваченных CRT. По-хорошему, использовать функции типа _endtrhead НЕ нужно.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: _beginthreadex и деструкторы
От: Andrew S Россия http://alchemy-lab.com
Дата: 05.10.04 21:16
Оценка: 1 (1)
SDB>Или вызвать деструктор(ы) явно непосредственно перед вызовом _endthreadex():


SDB>
SDB>unsigned int _stdcall ThreadLoading(void* p)
SDB>    {
SDB>        CSomeClass someObject;

SDB>        someObject.~CSomeClass();
SDB>        _endthreadex(0);
SDB>        return 0;
SDB>    }

SDB>


О боже мой... их нравы

А так не проще ли?

unsigned int _stdcall ThreadLoading(void* p)
{
    {
        CSomeClass someObject;
        ......
    }
    _endthreadex(0);
    return 0;
}
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: _beginthreadex и деструкторы
От: c-smile Канада http://terrainformatica.com
Дата: 06.10.04 03:15
Оценка: :))
Здравствуйте, SchweinDeBurg, Вы писали:

Суров ты брат Schwein.

SDB>Или вызвать деструктор(ы) явно непосредственно перед вызовом _endthreadex():


SDB>
SDB>unsigned int _stdcall ThreadLoading(void* p)
SDB>    {
SDB>        CSomeClass someObject;

SDB>        someObject.~CSomeClass();
SDB>        _endthreadex(0);
SDB>        return 0;
SDB>    }

SDB>
Re[4]: _beginthreadex и деструкторы
От: Esperar  
Дата: 06.10.04 05:42
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>А так не проще ли?


AS>
AS>unsigned int _stdcall ThreadLoading(void* p)
AS>{
AS>    {
AS>        CSomeClass someObject;
AS>        ......
AS>    }
AS>    _endthreadex(0);
AS>    return 0;
AS>}
AS>

и проще, и понятней — пусть господа объяснят тот скрытый смысл, который заставляет их вызывать деструктор явно
Re[5]: _beginthreadex и деструкторы
От: SchweinDeBurg Россия http://zarezky.spb.ru/
Дата: 06.10.04 05:52
Оценка:
Здравствуйте, Esperar, Вы писали:

E>и проще, и понятней — пусть господа объяснят тот скрытый смысл, который заставляет их вызывать деструктор явно


См. выделенное. ИМХО — у каждого свой "стиль" и свои критерии "простоты и понятности". Есть предложение — не устраивать флейм на эту и смежные темы. Думаю, что вопрос автора топика получил всестороннее освещение, были приведены различные варианты решения проблемы и исчерпывающе прокомментирован соответствующий раздел MSDN. Предлагаю на этом тему можно считать закрытой.
- Искренне ваш, Поросенок Пафнутий ~ ICQ#116846877
In Windows, there’s always a catch… © Paul DiLascia
Re: _beginthreadex и деструкторы
От: Аноним  
Дата: 06.10.04 11:56
Оценка:
Здравствуйте, VNG, Вы писали:

VNG>В итоге имеем — деструктор объекта someObject не вызывается.

Предложение RSDN team: создать картинку где аватар стучит по башке самое себя...
ИМХО, она была бы здесь (и еще во многих местах) крайне в тему.

VNG>Что я делаю не так

Вызываешь не ту функцию.
_endthreadex() для потока делает то же самое что и exit() для процесса. То есть, прибивает его на месте.
Раскрутки стека (и, соответсвенно выполнения деструкторов) при этом не происходит.

Если же ты хочешь чтобы при выходе из нитки деструкторы все-таки вызывались, попробуй такую технику:

    #define _endthreadex(exit_code) \
        throw EndThreadException(exit_code)

    unsigned int _stdcall ThreadLoading(void* p)
    {
        try {

            CSomeClass someObject;
            _endthreadex(0);

        }
        catch(EndThreadException const& e) {
            return e.exit_code();
        }
        return 0;
    }


Естественно, этот подход не без граблей. И самые "детские" грабли здесь — это то что выражение "catch(...){/*просто игнорируем исключение*/}" которое может встретиться в функциях вызываемых из ThreadLoading() немедлено обгадит всю малину. Лично меня это волнует не слишком (т.к. применение таких выражений как правило ставит вопрос о профпригодности применяющего их), но все-таки...

Выход, впрочем, есть.
— вместо "throw EndThreadException" применять setjmp()/longjmp() — это будет работать на Микрософтовских компиляторах. На остальных — это undefined behavior
— или же, применять structured exceptions с каким-нибудь навороченым ExceptionCode — это тоже будет работать на Микрософтовских компиляторах, на остальных даже не будет компилироваться.
Re: _beginthreadex и деструкторы
От: Ash-2 Россия  
Дата: 08.10.04 09:16
Оценка:
Здравствуйте, VNG, Вы писали:

VNG>Так вот какая проблема. Когда срабатывает _endthreadex(0), функция ожидания ::WaitForSingleObject(hThread, INFINITE) возвращается и соответсвенно следующей вызывается ::CloseHandle(hThread). В итоге имеем — деструктор объекта someObject не вызывается.


VNG>Что я делаю не так

VNG>Работаю с MSVC++7.1 и CRT, которая идет с ним же.
VNG>2Moderator. Просьба не отсылать в WinAPI или средства разработки.

Может я и не прав (под рукой нет msdn),
но _endthreadex(0) кажется относится к CRT (и соответственно потоко создавался через _beginthread). В этом случае: перед создаем потока инициализируется "часть crt", которая затем "освобождается" при завершении функции потока (Рихтер). Т.о. НЕЛЬЗЯ использовать _endthreadex(0) для корректного завершения потока и (ИМХО) обсуждать тут нечего: 1. если нужен корректный выход — _endthreadex быть не должно.
2. если _endthreadex все-таки используется, то остается только вопрос кол-во и размера утечек.
Re[2]: _beginthreadex и деструкторы
От: Andrew S Россия http://alchemy-lab.com
Дата: 08.10.04 09:51
Оценка:
Вы противоречите сами себе. Посмотрите ветку.

A2>Может я и не прав (под рукой нет msdn),

A2>но _endthreadex(0) кажется относится к CRT (и соответственно потоко создавался через _beginthread). В этом случае: перед создаем потока инициализируется "часть crt", которая затем "освобождается" при завершении функции потока (Рихтер). Т.о. НЕЛЬЗЯ использовать _endthreadex(0) для корректного завершения потока и (ИМХО) обсуждать тут нечего: 1. если нужен корректный выход — _endthreadex быть не должно.
A2>2. если _endthreadex все-таки используется, то остается только вопрос кол-во и размера утечек.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.