Является ли утечка std :: thread неопределенным поведением? - PullRequest
1 голос
/ 13 сентября 2011

Причина, по которой кому-то будет интересно

  //...
 new std::thread (func,arg1,arg2);

}

- это то, что деструктор std::thread (в отличие от boost::thread) убивает поток. func заканчивает некоторое время. Мой вопрос, это безопасно в случаях:

Случай 1: предположим, что функция принимает значение arg1, arg2.
Случай 2: предположим, что функция принимает arg1, arg2 по ссылке - это звучит плохо, если вы спросите меня, потому что я предполагаю, что в конце области, где создан поток, arg1 и arg2 будут очищены их деструкторами.

Кстати, деструктор std :: thread (то есть AFAIK, который вызывается после завершения func) достаточно умен, чтобы очистить все ресурсы, используемые потоком? Я имею в виду, если я создаю 1M потоков (ofc не одновременно) с новыми, и все они заканчиваются, я что-нибудь утекла навсегда?

Ответы [ 3 ]

10 голосов
/ 14 сентября 2011

Объект std :: thread представляет собой поток, это не «реальный» поток, а концепция, управляемая ОС.

Следовательно, здесь вы пропускаете объект std :: thread, потому что вы его не удаляете. Деструктор никогда не вызывается. Но поток, который он представлял, закончится, когда закончатся инструкции, как любой поток.

Если деструктор был вызван до конца инструкций, например, если бы вы создали этот объект в стеке, и в этом новом потоке нужно было многое сделать, то вызов деструктора срабатывает std :: terminate (). Вам необходимо вызвать detach (), чтобы позволить потоку продолжить работу после уничтожения экземпляра std :: thread.

Таким образом, вы должны явно указать, хотите ли вы, чтобы этот поток заканчивался при уничтожении экземпляра std :: thread: если вы хотите, чтобы он продолжался, вызовите detach (); если вы хотите дождаться его окончания, вызовите join ().

Так что в вашем случае вы теряете память, но поток должен продолжаться, так как объект std :: thread живет «вечно», потому что вы потеряли любой способ его управления.

1 голос
/ 13 сентября 2011

Кстати, деструктор std :: thread (то есть AFAIK, который вызывается после завершения func) достаточно умен, чтобы очистить все ресурсы, используемые потоком? Я имею в виду, если я создаю 1M потоков (ofc не одновременно) с новыми, и все они заканчиваются, я что-нибудь вытекла навсегда?

Обычно деструктор вызывается автоматически, когда объект в стеке выходит из области видимости (или во время разматывания стека, когда обнаружено исключение). Поскольку объект потока размещается в куче с использованием new, деструктор не будет вызываться автоматически, некоторый код должен delete объекту вызвать его деструктор. Другими словами, деструктор thread не вызывается, когда func() заканчивается.

1 голос
/ 13 сентября 2011

Это , а не ОК в соответствии с окончательным текстом.В частности, деструктор потока, который не был ни join ed, ни detach ed, вызовет std::terminate.

std::thread деструктор не вызывается при возврате обратного вызова, но когдаthread объект выходит из области видимости, как и любой другой объект.Таким образом, поток new 'd, который никогда не будет delete' d, никогда не будет разрушен, что приведет к утечке любого связанного состояния (и все может пойти ужасно неправильно, если / когда программа завершит работу с дополнительными потоками, которые все еще работают ...)

Чтобы ответить на ваш вопрос о временах жизни, std::thread похож на std::bind: он хранит копии своих аргументов и передает эти копии обратному вызову независимо от того, принимает ли обратный вызов свои аргументы по значению или по ссылке.Вы должны явно обернуть аргументы std::ref, чтобы получить ссылочную семантику.В этом случае, как обычно, вы должны убедиться, что нет оборванных ссылок (например, путем вызова thread::join() до того, как какие-либо ссылочные переменные выйдут из области видимости).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...