【问题标题】:How std::thread object copies argument?std::thread 对象如何复制参数?
【发布时间】:2020-01-07 23:10:35
【问题描述】:

问题已更新!

我有一个 std::string 对象,std::thread 应该将它复制到它的内部存储中,为什么下面的代码仍然不起作用?(已修复)

如果我分离 t(f, 5, std::string(buf)),则根本没有输出! (已修复)

#include <thread>
#include <iostream>
#include <unistd.h>

using namespace std;

void f(int i, const std::string &str) {
  printf("i = %d, str = %s\n", i, str.c_str());
}

void oops(int ival) {
  char *buf = new char[32]{0};
  snprintf(buf, 32, "%i", ival);
  // maybe danling pointer, if it's a danling pointer, the content of buf is undefined
  // in this program it happens to be 1999.
  std::thread t(f, 3, buf); 
  t.detach();

  delete [] buf; 
}

void not_oops(int ival) {
  char *buf = new char[32]{0};
  snprintf(buf, 32, "%i", ival);
  std::thread t(f, 5, std::string(buf));
  t.detach();

  delete [] buf;
}

int main() {
  oops(1992); // This is buggy
  not_oops(1999);
}

预期输出:

i = 3, str = 1992
i = 5, str = 1999

实际输出:

i = 3, str = 1999
i = 5, str = 1999

【问题讨论】:

  • 您需要在main 中添加一些延迟以等待结果(也许通过使用this_thread::sleep_for() ?)。两次调用detachmain 立即结束。您的not_oops 功能正常工作,当您修复延迟问题时,您将看到正确的结果。
  • 是的,在oops 它正在复制值。该值只是一个指针。
  • 但是输出还是不对...

标签: c++11 g++ ubuntu-18.04 clang++ stdthread


【解决方案1】:

你的程序在它完成之前完成,你的函数在线程完成之前退出作用域,杀死它。

void oops(int ival) {
  char *buf = new char[32]{0};
  snprintf(buf, 32, "%i", ival);
  std::thread t(f, 3, buf); // maybe danling pointer
  t.detach();     // no more waiting for it

  delete [] buf;  // thread is not started yet (probably)    
} // thread is destroyed ,  and std::string dies.

在不对代码进行大量更改的情况下使其工作的唯一方法是允许在外部管理线程。此外,您必须确保创建了一个新的 std::string,或者线程似乎对两者使用相同的存储。

void f(int i, const std::string &str) {
  printf("i = %d, str = %s\n", i, str.c_str());
}

std::thread *t;
void oops(int ival) {
  char *buf = new char[32]{0};
  snprintf(buf, 32, "%i", ival);
  t = new std::thread(f, 3, std::string(buf)); // maybe danling pointer
  //t.detach();

  delete [] buf; 
}

void not_oops(int ival) {
  char *buf = new char[32]{0};
  snprintf(buf, 32, "%i", ival);
  std::thread t(f, 5, std::string(buf)); // FIXME: why it won't work ?
  t.join();
  delete [] buf;
}

int main() {
  oops(1992); // This is buggy
  not_oops(1999);
  t->join();
  delete t;
}

【讨论】:

  • 感谢您的回答,如果我不想在 oops 函数之外管理 std::thread 对象怎么办?为什么 oops(1992) 和 oops(1999) 都打印 1999?
猜你喜欢
  • 2021-04-07
  • 2021-05-25
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
  • 2012-04-17
  • 2010-10-16
  • 2017-03-22
  • 1970-01-01
相关资源
最近更新 更多