在多线程应用程序中使用 stringstream 的分段错误(核心转储)

Segmentation fault (core dumped) using stringstream in multithread application

我正在尝试做一个简单的线程安全记录器,它将消息打印到控制台。

// Test function for check logger. It is work
void test(double& diff)
{
  std::vector<double> result;
  for( int counter = 0; counter < 100000; ++counter)
  {
    result.push_back(clock());

    std::string text = "counter = ";
    text.append(std::to_string(counter));
    LOG_MESSAGE(text); //<-- Correct log..
  }
  diff = clock() - result.front();

}

int main(int argc, char** argv)
{
  double time2;
  double time1;
  std::vector<double> timerResult;
  std::vector<std::thread> threadVector;

  time1 = clock();
  for(int i = 0; i < 5; ++i) //<-- Create 5 thread of test function
  {
    timerResult.push_back(0);
    threadVector.push_back(std::thread(test, std::ref(timerResult[i])));
  }
  for(std::thread& t : threadVector)
    t.join();
  time2 = clock(); //<-- Threads is finished

  double res = 0;
  for(double tRes : timerResult)
     res += tRes;
  res = res / static_cast<double>(CLOCKS_PER_SEC);

  std::string message; //<-- Generate final message
  message.append("Timer: ")
      .append(std::to_string((time2 - time1) / (double)CLOCKS_PER_SEC))
      .append(" - thread timer: ")
      .append(std::to_string(res));

  LOG_MESSAGE(message); //<-- Crash inside!!    

  return 0;
}

Logger 在线程中运行良好。但是当我尝试登录在 std::ostringstream 的析构函数中调用 SIGSEGV 信号的 main() 函数时(在构造日志消息的函数中):

static Logger::Core logger; //<--Global Logger variable

#define LOG_MESSAGE( TEXT ) logger.addNoteInLog(TEXT) //<-- Define for log message

void Core::addNoteInLog(const Message &message) //<-- threadsafe log function
{  
  std::string text;
  message.generateString(text); //<-- [Crash here] generate log message
  g_lock.lock();
  std::cout << text;
  g_lock.unlock();
}

void Message::generateString(std::string& text) const
{
  text.clear();
  tm *ltm = localtime(&mDate);

  std::ostringstream data; //<-- [Crash here] function is finished, but cannot destruct object.
  data << 1900 + ltm->tm_year << "/"
       << 1 + ltm->tm_mon << "/"
       << ltm->tm_mday << "\t";
  data << "[INF] - ";
  data << std::this_thread::get_id() << " - "
       << mMessage << "\n";

  text = data.str();
}

我不明白为什么记录器在线程中可以工作,但在 main() 函数中崩溃了。使用排除法,发现错误发生的时间:

QtCreater 中的 say 调试器。

在 Ubuntu OS 中构建,gcc 版本 5.4.0,编译标志:-std=c++17 -pthread -Wall

This 是我的 git 存储库,有错误。

问题已解决。 正如评论中所说,第 threadVector.push_back(std::thread(test, std::ref(timerResult[i]))); 行不正确,因为 timerResult 中的内存重新分配是在调用 push_back 5 次后完成的,并且 ref(timerResult[i]) 传递引用是不正确的.

正确代码:

    int main(int argc, char** argv)
    {
      double time2;
      double time1;
      std::vector<double> timerResult (5); //<-- Create filling of vector
      std::vector<std::thread> threadVector;

      time1 = clock();
      for(int i = 0; i < 5; ++i)
      {
        //timerResult.push_back(0); //<-- incorrect filling of vector
        threadVector.push_back(std::thread(test, std::ref(timerResult[i])));
      }
      for(std::thread& t : threadVector)
        t.join();
      time2 = clock();
      ...
    }