在向量成员变量中存储线程触发断点

Posted

技术标签:

【中文标题】在向量成员变量中存储线程触发断点【英文标题】:Storing thread in vector member variable triggers breakpoint 【发布时间】:2021-01-06 08:32:40 【问题描述】:

我有一个名为 Executor 的类,其中一个 vector 作为成员变量。 submit(const std::function& f) 成员函数应该将传递的 lambda 作为线程启动并将其添加到向量中。析构函数连接存储在向量中的所有线程。 第一个 lambda 打印结果,但之后我的代码以某种方式运行到断点。 我做错了什么?

这是我的 Executor.h 代码:

#include <thread>
#include <mutex>
#include <iostream>
#include <vector>
#include <functional>

using namespace std;
class Executor

protected:
    vector<thread*> threads;
    mutex m;
public:
    void submit(const std::function<void()>& f);
    Executor();
    ~Executor();
;

Executor.cpp:

#include "Executor.h"

void Executor::submit(const std::function<void()>& f)

    
    
        lock_guard<mutex> lock(m);
        thread t(f);
        
        threads.push_back(&t);
    
    


Executor::Executor() 

Executor::~Executor()

    for (unsigned int i = 0; i < threads.size(); i++)
    
        threads.at(i)->join();
        delete threads.at(i);
    
    threads.clear();

还有main():

Executor ex;
        auto fact = []()cout<< "factor(55) = " << factor(55); ;
        auto pk = []()cout << "P2(100, 50) = " << P2(100, 50); ;
        auto fib = []()cout << "fibonacci(45) = " << fibonacci(45); ;


        ex.submit(fact);
        ex.submit(pk);
        ex.submit(fib);

【问题讨论】:

不能存储指向局部变量的指针 为什么会有一个指向线程的指针向量?这没有任何意义。自己创建一个线程对象向量。 【参考方案1】:

threads.push_back(&amp;t); 中,指针&amp;t 仅在声明t 的范围结束之前有效。这会导致3 个问题:

    submit 内的作用域结束时,线程被破坏而不调用join,导致std::terminate 被调用 在Executor 的析构函数中,-&gt;join 被一个悬空指针调用 在Executor 的析构函数中,你调用delete 来处理没有分配new 的东西

此代码中无需使用指针,如果您将线程直接存储在向量中,您的代码会更简单、更安全:

class Executor

protected:
    vector<thread> threads;
    mutex m;
public:
    void submit(const std::function<void()>& f);
    Executor();
    ~Executor();

    Executor(const Executor&) = delete;
    Executor& operator=(const Executor&) = delete;
;

void Executor::submit(const std::function<void()>& f)
  
    
        lock_guard<mutex> lock(m);
        threads.emplace_back(f);
       


Executor::Executor() 

Executor::~Executor()

    for (auto& thread : threads)
    
        thread.join();
    
    threads.clear();

注意我还删除了复制构造函数和赋值运算符以符合rule of three

【讨论】:

以上是关于在向量成员变量中存储线程触发断点的主要内容,如果未能解决你的问题,请参考以下文章

在一个线程中修改成员变量并在另一个线程中读取

c ++在析构函数中删除向量类成员内存

在构造函数中初始化成员变量二维向量

JVM理论:(三/7)关于类变量成员变量局部变量的案例总结

从类指针向量创建成员变量向量

java变量存储