<目次>
(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)