C++ - "в местном времени" эта функция или переменная могут быть небезопасными

Я пишу простой класс ведения журнала на С++ для учебных целей. Мой код содержит функцию, которая возвращает строку сегодняшней даты. Однако я получаю сообщение об ошибке компилятора всякий раз, когда вызывается "localtime".

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;
}

Я пытался использовать #define _CRT_SECURE_NO_WARNINGS. Не помогло и появилась та же ошибка. Я также попытался поместить _CRT_SECURE_NO_WARNINGS в определения препроцессора в свойствах проекта. Это дало неразрешенную внешнюю ошибку.

У кого-нибудь есть идеи, что делать?


person ChiefHagno    schedule 26.06.2016    source источник
comment
Где точное предупреждение? localtime может быть опасным в использовании, потому что он возвращает указатель на область памяти, которой он владеет, поэтому, если вы вызываете его несколько раз, вам нужно убедиться, что каждый раз вы копируете структуру. Кроме того, кстати, из-за того, как вы создаете строку, если вы получаете 2112016, вы не знаете, 21/1/2016 или 2/11/2016.   -  person Klitos Kyriacou    schedule 26.06.2016
comment
Не используйте эту функцию по причине, указанной в предупреждении.   -  person Ben    schedule 11.04.2018


Ответы (2)


Попробуйте #define _CRT_SECURE_NO_WARNINGS перед #include любыми другими заголовочными файлами, например следующий код

#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
//your code
person Null    schedule 26.06.2016
comment
Не делайте этого. Вместо этого серьезно отнеситесь к предупреждению безопасности CRT! - person Ben; 11.04.2018

Проблема в том, что std::localtime не является потокобезопасным, поскольку использует статический буфер (общий для потоков). И у POSIX, и у Windows есть безопасные альтернативы: localtime_r и localtime_s.

Вот что я делаю:

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)};
}
person Galik    schedule 26.06.2016
comment
лучший ответ, чем выбранный - person elven_inside; 11.04.2018