У меня большой проект по статическому анализу исходного кода, и все успешно компилируется, кроме одного. Я предоставил сообщение об ошибке в заголовке. Меня смущает то, что выдает сообщение об ошибке «небезопасно». Я думал, что это должно быть просто предупреждение, а не ошибка. Кстати, я использую 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());
}
}
Если вы посмотрите на описание 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';
}
что даже лучше, так как вам больше не нужно беспокоиться о возможном переполнении буфера.
Если вы уверены, что в вашем коде нет проблем с безопасностью, вы можете отключить #pragma warning(disable : 4996)
,
Да, это должно быть просто предупреждение, а не ошибка.
Чтобы получить простое предупреждение вместо ошибки, отключите проверку SDL в проекте VS (в Свойствах конфигурации -> C / C ++ -> вкладка Общие).
std::ctime
не является потокобезопасным по двум причинам:
std::tm
это разделяется несколькими функциями.char
массив и возвращает указатель на этот массив.Существует вероятность столкновения, если у вас есть другие потоки, которые вызывают std::gmtime
, std::localtime
, или же std::ctime
,
Лучше всего преобразовать этот вызов в std::ctime
на звонок в std::strftime
, Это согласуется с POSIX, который считает ctime
устареть и рекомендует использовать strftime
вместо него.
против 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 … по-старому ..