コンソールにメッセージを出力する簡単なスレッドセーフロガーを試してみました。マルチスレッドアプリケーションでstringstreamを使用したセグメンテーションフォルト(コアダンプ)
// 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;
}
ロガーはスレッドで正常に動作します。しかし、私は(構造ログメッセージの機能で)の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();
}
が、私はスレッドでロガーが仕事である理由を理解しないが、メインで()関数がクラッシュしました。排除法を用いて、私は、エラーが発生したときに判明:
- Iは、5(またはそれ以上)を使用する場合generateString中にstringstream又はostringstreamまたは文字列を使用すると、試験機能が
- 空でない場合
- をスレッド.append()(最後のケースでは、同じ場所のstd :: stringデストラクタのアプリケーションクラッシュ)
QtCreaterのデバッガは何ですか? UbuntuのOSで
ビルド、gccのバージョン5.4.0、コンパイルフラグ:-std=c++17 -pthread -Wall
Thisがエラーと私のgitリポジトリです。
FYIドキュメントは 'localtime'はスレッドセーフでない場合があることに注意してください。ロック内の 'generateString'への呼び出しを移動するとどうなりますか? –
セグメンテーションフォルトが青色から出ない。あなたはデバッガのスタックトレースを調べましたか?どこから来たのでしょうか? – user0042
あなたのベクトルをチェックしますか?ベクトルが大きくなるとベクトルが完全に再割り当てされるので、スレッドがゴミを指している可能性があることを覚えておいてください。予備を使用してベクトルのサイズを事前に設定すると、ヘルプになる可能性があります。 –