ошибка C4996: «ctime»: эта функция или переменная может быть небезопасной

У меня большой проект по статическому анализу исходного кода, и все успешно компилируется, кроме одного. Я предоставил сообщение об ошибке в заголовке. Меня смущает то, что выдает сообщение об ошибке «небезопасно». Я думал, что это должно быть просто предупреждение, а не ошибка. Кстати, я использую Visual Studio 2012. Вот часть кода, где я получаю сообщение об ошибке, в ctime. Если кто-то может помочь мне преодолеть эту ошибку, я был бы рад.

void CppCheckExecutor::reportProgress(const std::string &filename, const char stage[], const std::size_t value)
{
(void)filename;

if (!time1)
return;

// Report progress messages every 10 seconds
const std::time_t time2 = std::time(NULL);
if (time2 >= (time1 + 10)) {
time1 = time2;

// current time in the format "Www Mmm dd hh:mm:ss yyyy"const std::string str(std::ctime(&time2));

// format a progress message
std::ostringstream ostr;
ostr << "progress: "<< stage
<< ' ' << value << '%';
if (_settings->_verbose)
ostr << " time=" << str.substr(11, 8);

// Report progress message
reportOut(ostr.str());
}
}

5

Решение

Если вы посмотрите на описание CTime вы заметите:

Эта функция возвращает указатель на статические данные и не является потокобезопасным. Кроме того, он изменяет статический тм объект которым можно поделиться с gmtime и localtime. POSIX помечает эту функцию как устаревшую и рекомендует вместо нее strftime.

поведение может быть неопределенным для значений time_t, результатом которых является строка длиной более 25 символов (например, год 10000)

… это много вещей для беспокойства.

С другой стороны, если вы посмотрите на STRFTIME:

size_t strftime (char * str, size_t count, const char * format, tm * time);

Возвращаемое значение

количество байтов, записанных в массив символов, на которые указывает str, не включая завершающий ‘\ 0’ в случае успеха. Если число было достигнуто до того, как вся строка может быть сохранена, возвращается 0 и содержимое не определено.

Все параметры являются явными, так что вы полностью контролируете возможные гонки данных, и также нет риска переполнения предоставленного буфера.

Это C-way, а C ++ вводит <chrono> в котором конкретная функция std::put_time также может использоваться для вывода времени в поток:

#include <iostream>
#include <iomanip>
#include <ctime>
#include <chrono>

int main() {
std::time_t const now_c = std::time();
std::cout << "One day ago, the time was "<< std::put_time(std::localtime(&now_c), "%F %T") << '\n';
}

что даже лучше, так как вам больше не нужно беспокоиться о возможном переполнении буфера.

5

Другие решения

Если вы уверены, что в вашем коде нет проблем с безопасностью, вы можете отключить #pragma warning(disable : 4996),

5

Да, это должно быть просто предупреждение, а не ошибка.
Чтобы получить простое предупреждение вместо ошибки, отключите проверку SDL в проекте VS (в Свойствах конфигурации -> C / C ++ -> вкладка Общие).

5

std::ctime не является потокобезопасным по двум причинам:

  • Это может изменить глобальный объект типа std::tm это разделяется несколькими функциями.
  • Это изменяет глобальный char массив и возвращает указатель на этот массив.

Существует вероятность столкновения, если у вас есть другие потоки, которые вызывают std::gmtime, std::localtime, или же std::ctime,

Лучше всего преобразовать этот вызов в std::ctime на звонок в std::strftime, Это согласуется с POSIX, который считает ctime устареть и рекомендует использовать strftime вместо него.

2

против 2017 года:

#include "stdafx.h"

#include <iostream>
#include <iomanip>
#include <ctime>
#include <chrono>

int main() {
std::time_t const now_c = std::time(NULL);
auto s = std::put_time(std::localtime(&now_c), "%F %T");
std::cout << s << std::endl;
}

но вы все равно получите:

….cpp (31): предупреждение C4996: «местное время»: эта функция или переменная может быть небезопасной. Попробуйте вместо этого использовать localtime_s. Чтобы отключить устаревание, используйте _CRT_SECURE_NO_WARNINGS. Смотрите справку для деталей.

Для предотвращения вы можете использовать:

errno_t err;
struct tm time_info;
time_t time_create = time(NULL);
localtime_s(&time_info, &time_create);
char timebuf[26];
err = asctime_s(timebuf, 26, &time_info);

обычный C взят частично из MSDN … по-старому ..

0
По вопросам рекламы [email protected]