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

3

16

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?

Sterling answered 26/6, 2016 at 0:4 Comment(2)
Where is the exact warning message? 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.Mcglone
Do not use this function for the reason given in the warning.Couldst
P
-4

Try to #define _CRT_SECURE_NO_WARNINGS before #include any other header files, like the following code

#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
//your code
Parting answered 26/6, 2016 at 2:44 Comment(1)
Do not do this. Instead take the CRT security warning seriously!Couldst
P
64

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)};
}
Proximity answered 26/6, 2016 at 0:26 Comment(1)
better answer than the one selectedPepin
B
4

updated answer with C++20 chrono library

    const auto now            = std::chrono::system_clock::now();
    const auto time_zone      = std::chrono::current_zone();
    const auto local_time     = time_zone->to_local(now);
    const auto time_point     = std::chrono::time_point_cast<std::chrono::days>(local_time);
    const auto year_month_day = std::chrono::year_month_day{ time_point };

    int year  = static_cast<int>(year_month_day.year());
    int month = static_cast<unsigned>(year_month_day.month());
    int day   = static_cast<unsigned>(year_month_day.day());
Bedabble answered 22/8, 2023 at 5:33 Comment(1)
This gives the current UTC date. You can get the current local date by first transforming system_clock::now() to a local_time by using current_zone()->to_local().Figure
P
-4

Try to #define _CRT_SECURE_NO_WARNINGS before #include any other header files, like the following code

#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
//your code
Parting answered 26/6, 2016 at 2:44 Comment(1)
Do not do this. Instead take the CRT security warning seriously!Couldst

© 2022 - 2025 — McMap. All rights reserved.