Так вот какая проблема. Когда срабатывает _endthreadex(0), функция ожидания ::WaitForSingleObject(hThread, INFINITE) возвращается и соответсвенно следующей вызывается ::CloseHandle(hThread). В итоге имеем — деструктор объекта someObject не вызывается.
Что я делаю не так
Работаю с MSVC++7.1 и CRT, которая идет с ним же.
2Moderator. Просьба не отсылать в WinAPI или средства разработки.
VNG>Так вот какая проблема. Когда срабатывает _endthreadex(0), функция ожидания ::WaitForSingleObject(hThread, INFINITE) возвращается и соответсвенно следующей вызывается ::CloseHandle(hThread). В итоге имеем — деструктор объекта someObject не вызывается.
_endthreadex завершает выполнение потока в момент ее вызова, а объект находиться в стеке.
В вашем примере вызов _endthreadex стоит убрать, т.к. поток завершиться сам собой при выходе из функции.
Здравствуйте, AlexBS, Вы писали:
ABS>_endthreadex завершает выполнение потока в момент ее вызова, а объект находиться в стеке. ABS>В вашем примере вызов _endthreadex стоит убрать, т.к. поток завершиться сам собой при выходе из функции.
Или вызвать деструктор(ы) явно непосредственно перед вызовом _endthreadex():
Здравствуйте, 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.
Здравствуйте, 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.
Здравствуйте, 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().
Я кончил, джентльмены, мне остается только поблагодарить вас за внимание.
SDB>>Terminating a thread with a call to endthread or _endthreadex helps to ensure proper recovery of resources allocated for the thread.
A>Это в равной степени относится как к явному, так и к неявному вызову _endthreadex().
Дай то Бог! Но поскольку "даже у параноиков могут быть враги" ( (с) Гувер ), япредпочитаю явный вызов (с предшествующим явным вызовом деструкторов локальных объектов).
Здравствуйте, VNG, Вы писали:
VNG>Здравствуйте, AlexBS, Вы писали:
ABS>>В вашем примере вызов _endthreadex стоит убрать, т.к. поток завершиться сам собой при выходе из функции.
VNG>Будет ли это кошерно? В MSDN по-моему написано, что обязательно надо вызывать _endthreadex, если начинался поток с _beginthreadex.
Здравствуйте, <Аноним>, Вы писали:
А>А если исходники _beginthreadex посмотреть?
Это может дать представление о том, "как оно устроено сейчас". Но если играть по правилам — нужно в первую очередь смотреть, что написано в MSDN. Это более веская гарантия правильности кодирования.
Я кончил, джентльмены, мне остается только поблагодарить вас за внимание.
Здравствуйте, 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 НЕ нужно.
Здравствуйте, Esperar, Вы писали:
E>и проще, и понятней — пусть господа объяснят тот скрытый смысл, который заставляет их вызывать деструктор явно
См. выделенное. ИМХО — у каждого свой "стиль" и свои критерии "простоты и понятности". Есть предложение — не устраивать флейм на эту и смежные темы. Думаю, что вопрос автора топика получил всестороннее освещение, были приведены различные варианты решения проблемы и исчерпывающе прокомментирован соответствующий раздел MSDN. Предлагаю на этом тему можно считать закрытой.
Здравствуйте, VNG, Вы писали:
VNG>В итоге имеем — деструктор объекта someObject не вызывается.
Предложение RSDN team: создать картинку где аватар стучит по башке самое себя...
ИМХО, она была бы здесь (и еще во многих местах) крайне в тему.
VNG>Что я делаю не так
Вызываешь не ту функцию.
_endthreadex() для потока делает то же самое что и exit() для процесса. То есть, прибивает его на месте.
Раскрутки стека (и, соответсвенно выполнения деструкторов) при этом не происходит.
Если же ты хочешь чтобы при выходе из нитки деструкторы все-таки вызывались, попробуй такую технику:
Естественно, этот подход не без граблей. И самые "детские" грабли здесь — это то что выражение "catch(...){/*просто игнорируем исключение*/}" которое может встретиться в функциях вызываемых из ThreadLoading() немедлено обгадит всю малину. Лично меня это волнует не слишком (т.к. применение таких выражений как правило ставит вопрос о профпригодности применяющего их), но все-таки...
Выход, впрочем, есть.
— вместо "throw EndThreadException" применять setjmp()/longjmp() — это будет работать на Микрософтовских компиляторах. На остальных — это undefined behavior
— или же, применять structured exceptions с каким-нибудь навороченым ExceptionCode — это тоже будет работать на Микрософтовских компиляторах, на остальных даже не будет компилироваться.
Здравствуйте, 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 все-таки используется, то остается только вопрос кол-во и размера утечек.
Вы противоречите сами себе. Посмотрите ветку.
A2>Может я и не прав (под рукой нет msdn), A2>но _endthreadex(0) кажется относится к CRT (и соответственно потоко создавался через _beginthread). В этом случае: перед создаем потока инициализируется "часть crt", которая затем "освобождается" при завершении функции потока (Рихтер). Т.о. НЕЛЬЗЯ использовать _endthreadex(0) для корректного завершения потока и (ИМХО) обсуждать тут нечего: 1. если нужен корректный выход — _endthreadex быть не должно. A2>2. если _endthreadex все-таки используется, то остается только вопрос кол-во и размера утечек.