在C ++中创建std线程会使程序崩溃

时间:2015-11-25 05:22:26

标签: c++ multithreading visual-c++ visual-studio-2015 std

每当我使用线程执行以下代码时,程序都会出现此错误:

调试错误! 程序:... / path/to/.exe

abort()被称为

我想创建一个调用成员函数的线程。这是我正在使用的功能:

void ServerVote::createConnexionThreads()
{
    for (int i = 0; i <= 50; ++i)
    {
        m_connexionThreads.push_back(&(std::thread(&ServerVote::acceptConnection,*this, i)));
    }
    for (int i = 0; i <= 50; ++i)
    {
        m_connexionThreads[i]->join();
    }
}

如果需要,我可以提供额外的代码。使用调试器时,我发现在线程被push_back之后,程序在创建第一个线程后立即崩溃。然后调用~thread()并在此函数内崩溃。这是矢量声明:

std::vector<std::thread*> m_connexionThreads;

我正在使用Visual Studio 2015.acceptConnection函数在其中有一段时间(true),并计划稍后终止。

编辑:

感谢您的回答,但在使用线程对象而不是指针时无法编译。所以,当我试图进入这个载体时:

std::vector<std::thread> m_connexionThreads;

for (int i = 0; i <= 50; ++i)
{
        m_connexionThreads.push_back((std::thread(&ServerVote::acceptConnection,*this, i)));
}

编译时出现此错误:

error C2280: 'std::thread::thread(const std::thread &)': attempting to reference a deleted function

2 个答案:

答案 0 :(得分:3)

您不应尝试在任何上下文中使用临时地址。事实上,这是MSVC中允许此代码的错误。任何符合标准的编译器都会在这里产生错误。

相反,您应该使用这样的线程对象(请参阅我的编辑下面的代码,了解为什么这是首选):

#include <thread>
#include <vector>

void acceptConnection(int);

void foo() {
  std::vector<std::thread> vec;
  for (int i = 0; i <= 50; ++i)
        vec.push_back(std::thread(acceptConnection, i));
}

为什么这种方法比使用分配指向线程对象的指针更受欢迎?有很多好处:

  1. 输入较少 - 即使没有别的,所有事情都是平等的(虽然它们不是!),打字越少,打字越多。
  2. 使用指针时要小心。例如,你不应该使用原始指针作为矢量数据类型,你应该使用unique_ptr来确保自动清理内存 - 这使语法更加丑陋!
  3. 使用动态分配的内存会降低性能。您被击中两次 - 第一次分配内存时,第二次释放内存时。为什么要遭受这种惩罚?

答案 1 :(得分:2)

您正在堆栈中创建一个本地线程实例,获取其地址并将其推送到向量。线程对象将在方法退出时被删除,因此您将留下指向已删除对象的指针。

您应该使用new在堆中创建线程对象,以便在方法退出时不会删除它,或者不使用指向线程对象的指针。