Работает ли использование локальных в качестве аргументов в pthread_create()?
Это в основном вопрос о сфере и темах. Допустим, у нас есть следующая структура.
struct Test
{
int number;
std::string name;
};
Экземпляр этой структуры будет использоваться в качестве аргумента в функции pthread_create. Вот пример того, как это может выглядеть.
pthread_t tid[5];
for(int i = 0; i < 5; ++i)
{
Test test;
test.number = 5;
test.name = "test";
pthread_create(&tid[i], NULL, func, (void *)&test);
}
Это приемлемо? Поскольку test объявлен в области действия for, это означает, что мы можем полагаться только на то, что он существует во время одной итерации цикла for.
Когда вызывается pthread_create, указатель для проверки дается в качестве аргумента. Это означает, что func получает тот же указатель, который передается в pthread_create. Это означает, что когда тест выходит из области видимости, мы больше не можем полагаться на этот указатель, ссылающийся на тест. Если бы нам нужно было создать больше местных жителей, а значит, и изменить стек, местоположение, на которое указывает указатель, было бы перезаписано этими новыми местными жителями. Это правильно?
1 ответ
Это приемлемо?
В общем, нет, по причинам, которые вы указали. В частности, функция входа потока не может начать выполняться до тех пор, пока объект Test не будет уничтожен, или объект Test может быть уничтожен, пока функция входа потока все еще использует его. Любая из этих возможностей приведет к неопределенному поведению (и программе, которая работает корректно только "иногда").
Вы должны гарантировать, что данные, которые вы передаете потоку, остаются действительными до тех пор, пока поток должен их использовать. Один из способов сделать это - разместить этот объект Test в куче и вызвать вызов потока. delete
на Test-указатель, когда это сделано, используя его. В качестве альтернативы вы можете использовать условную переменную для "приостановки" основного потока до тех пор, пока дочерний pthread не сообщит, что он завершил доступ к тесту в стеке основного потока, так что теперь основной поток может безопасно продолжить выполнение.
Если бы нам нужно было создать больше местных жителей, а значит, и изменить стек, местоположение, на которое указывает указатель, было бы перезаписано этими новыми местными жителями. Это правильно?
Да, вы правильно поняли проблему.