Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - 'localtime' this function or variable may be unsafe

I am writing a simple logging class in C++ for learning purposes. My code contains a function that returns a string of today's date. However, I get a compiler error whenever 'localtime' is called.

std::string get_date_string(time_t *time) {
    struct tm *now = localtime(time);
    std::string date = std::to_string(now->tm_mday) + std::to_string(now->tm_mon) + std::to_string(now->tm_year);
    return date;
}

I have tried using #define _CRT_SECURE_NO_WARNINGS. It didn't work and the same error appeared. I also tried putting _CRT_SECURE_NO_WARNINGS inside the preprocessor definitions in the project properties. This gave an unresolved external error.

Does anyone have any ideas on what to do?

like image 996
ChiefHagno Avatar asked Jun 26 '16 00:06

ChiefHagno


People also ask

Why is Localtime unsafe?

localtime can be dangerous to use because it returns a pointer to a memory area which it owns, so if you call it multiple times you need to make sure each time you copy the struct. Also, by the way, the way you create a string, if you get "2112016" you don't know if that's 21/1/2016 or 2/11/2016.

How do I get Localtime in C++?

The localtime() function takes a pointer of type time_t as its argument and returns a pointer object of structure tm . The value returned by localtime() function is the local time. Then, the hours, minutes and seconds can be accessed using tm_hour , tm_min and tm_sec respectively.

Is Ctime thread-safe?

ctime returns a pointer to static data and is not thread-safe. In addition, it modifies the static tm object which may be shared with gmtime and localtime.


1 Answers

The problem is that std::localtime is not thread-safe because it uses a static buffer (shared between threads). Both POSIX and Windows have safe alternatives: localtime_r and localtime_s.

Here is what I do:

inline std::tm localtime_xp(std::time_t timer)
{
    std::tm bt {};
#if defined(__unix__)
    localtime_r(&timer, &bt);
#elif defined(_MSC_VER)
    localtime_s(&bt, &timer);
#else
    static std::mutex mtx;
    std::lock_guard<std::mutex> lock(mtx);
    bt = *std::localtime(&timer);
#endif
    return bt;
}

// default = "YYYY-MM-DD HH:MM:SS"
inline std::string time_stamp(const std::string& fmt = "%F %T")
{
    auto bt = localtime_xp(std::time(0));
    char buf[64];
    return {buf, std::strftime(buf, sizeof(buf), fmt.c_str(), &bt)};
}
like image 63
Galik Avatar answered Sep 30 '22 01:09

Galik