<目次>
(1) C++のlocaltime関数がスレッドアンセーフである理由と使用上の注意点
(1-1) localtime関数がスレッドアンセーフである理由
(1-2) localtime関数がスレッドアンセーフによるNG例
(1-3) localtime_r関数を使ったスレッドセーフなOK例
(1-4) 他のスレッドアンセーフな関数
(1) C++のlocaltime関数がスレッドアンセーフである理由と使用上の注意点
(1-1) localtime関数がスレッドアンセーフである理由
struct tm * localtime (const time_t * XXXX);
(1-2) localtime関数がスレッドアンセーフによるNG例
#include <time.h>
#include <iostream>
#include <chrono>
#include <thread>
#pragma warning(disable: 4996)
using namespace std;
int main ()
{
time_t t1 = time(nullptr);
this_thread::sleep_for(chrono::seconds(2));
time_t t2 = time(nullptr);
//# tm*はstaticな領域を参照しており、
//# この後、新規にlocaltime関数をコールした場合に上書きされてしまう。
//# (1)localtimeの初回呼び出し(t1のlocaltime結果「t1_tm」を出力)
tm* t1_tm = localtime(&t1);
cout<<"t1 (Before): "<<asctime(t1_tm)<<'\n';
//# (2)localtimeの2回目呼び出し(t1_tmはt2_tmの値で上書きされてしまう事の確認)
tm* t2_tm = localtime(&t2);
cout<<"t1 (After): "<<asctime(t1_tm)<<'\n';
cout<<"t2 : "<<asctime(t2_tm)<<'\n';
return 0;
}
(図111①)

・実行結果
(図111②)

(1-3) localtime_r関数を使ったスレッドセーフなOK例
struct tm *localtime_r( const time_t *XXXX, struct tm *YYYY );
(OK例)
#include <time.h>
#include <iostream>
#include <chrono>
#include <thread>
#pragma warning(disable: 4996)
using namespace std;
int main ()
{
time_t t1 = time(nullptr);
tm t1_buf;
this_thread::sleep_for(chrono::seconds(2));
time_t t2 = time(nullptr);
tm t2_buf;
//# tm*はstaticな領域を参照しており、
//# この後、新規にlocaltime関数をコールした場合に上書きされてしまう。
//# (1)localtimeの初回呼び出し(t1のlocaltime結果「t1_tm」を出力)
//tm* t1_tm = localtime(&t1);
localtime_r(&t1,&t1_buf);
cout<<"t1 (Before): "<<asctime(&t1_buf)<<'\n';
//# (2)localtimeの2回目呼び出し(t1_tmはt2_tmの値で上書きされてしまう事の確認)
//#
//tm* t2_tm = localtime(&t2);
localtime_r(&t2,&t2_buf);
cout<<"t1 (After): "<<asctime(&t1_buf)<<'\n';
cout<<"t2 : "<<asctime(&t2_buf)<<'\n';
return 0;
}
(図131)

・実行結果
(図132)
