我编写了一个示例程序来显示我的问题 - 我不明白为什么firstVersion()
工作正常,secondVersion()
给了我错误:terminate called without an active exception Aborted
。谢谢你的回答!
这是代码:)
#include <thread>
#include <iostream>
#include <chrono>
using namespace std;
const int threadCount = 100;
int N = 1;
void f() {
N++;
}
void firstVersion() {
thread * t[threadCount];
for(int i = 0; i < threadCount; i++) {
thread * ti = new thread{f};
t[i] = ti;
}
for(int i = 0; i < threadCount; i++) {
t[i]->join();
delete t[i];
}
}
void secondVersion() {
thread * t[threadCount];
for(int i = 0; i < threadCount; i++) {
thread ti{f};
t[i] = &ti;
}
for(int i = 0; i < threadCount; i++)
t[i]->join();
}
int main() {
//firstVersion();
secondVersion();
return 0;
}
答案 0 :(得分:2)
std::thread
需要join
或detach
其析构函数运行。
因为您没有调用任何detach
或join
std::thread
的名为std::abort
的析构函数。
join
)之前,首先delete
编辑线程:
t[i]->join();
delete t[i];
幸运的是,它阻止了更糟糕的事情:悬空指针。在每个结尾
for(int i = 0; i < threadCount; i++) {
thread ti{f};
t[i] = &ti;
}
ti
已经死了,你会指向一个不再存在的物体。你违反了C ++的一些基本规则永远不会返回或保持指针或对其范围之外的局部变量的引用
答案 1 :(得分:1)
第二个版本失败,因为在您致电join()
之前,线程的生命周期在for循环结束时结束。
void secondVersion() {
thread * t[threadCount];
for(int i = 0; i < threadCount; i++) {
thread ti{f}; // local object of thread
t[i] = &ti;
} // the object dies without a join()
您的示例可以简化为:
void SomeFunc() {}
int main()
{
std::thread* tp;
//{
std::thread t{SomeFunc};
tp= &t;
//} // if the closing brace is present, object t calls destructor here!
tp->join();
}
如果您查看STL,可以找到以下代码:
~thread()
{
if (joinable())
std::terminate();
}
这只会导致调用terminate
。
因此示例代码有两个错误:
1)创建指向在使用指针之前死亡的对象的指针,该对象称为dangling reference
2)因为线程对象在调用join()之前死掉,所以它只是调用terminate。