Почему передача временного объекта в другой поток не вызывает неопределенного поведения? - PullRequest
0 голосов
/ 26 апреля 2018

Ниже приведен пример из C ++ параллелизма в действии $ 2.2

void f(int i,std::string const& s);
void oops(int some_param)
{
  char buffer[1024];
  sprintf(buffer, "%i",some_param);
  std::thread t(f,3,buffer);
  t.detach();
}  

И автор говорит, что это неопределенное поведение:

В этом случаеэто указатель на локальную переменную buffer, которая передается в новый поток, и существует значительная вероятность того, что функция упс выйдет до того, как буфер будет преобразован в std::string в новом потоке, что приведет к неопределенное поведение .Решение заключается в приведении к std::string перед передачей буфера в конструктор std :: thread:

void f(int i,std::string const& s);
void not_oops(int some_param)
{
  char buffer[1024];
  sprintf(buffer,"%i",some_param);
  std::thread t(f,3,std::string(buffer));
  t.detach();
}   

Но я запутался в этом.Потому что, насколько я понимаю, нет никакой разницы между двумя формами:

В первом фрагменте кода при передаче buffer функции в качестве параметра также будет создан временный объект std::stringи связать параметр функции с этим временным объектом. Так что это точно так же со вторым фрагментом кода. Единственное отличие состоит в том, что временный объект в первом объекте генерируется неявно компилятором, а второй явно пользователем.

1 Ответ

0 голосов
/ 26 апреля 2018

Здесь есть два шага:

  • Независимо от того, что вы передаете конструктору std::thread, этот конструктор копируется с распадом в хранилище, доступное для нового потока.
  • Затем новый поток вызывает вызываемый объект, используя эти скопированные аргументы.

Первый фрагмент копирует указатель на буфер.Вызов вызываемого объекта нового потока преобразует этот указатель в std::string, но к тому времени буфер может быть уже удален.

Второй фрагмент выполняет преобразование в исходном потоке, когда он гарантированно будет действительным,Временный std::string затем перемещается конструктором std::thread в промежуточное хранилище.

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