简体   繁体   English

错误C4996:'ctime':此函数或变量可能不安全

[英]error C4996: 'ctime': This function or variable may be unsafe

I have a large project about static source code analysis, and everything compiles successfully, except for one thing. 我有一个关于静态源代码分析的大型项目,一切都成功编译,除了一件事。 I have provided the error message in the title. 我在标题中提供了错误消息。 The point that confuses me is that it gives an error message saying unsafe. 令我困惑的一点是,它给出了一条错误信息,说不安全。 I thought it should be just warning, not an error. 我认为应该只是警告,而不是错误。 By the way, I'm using Visual Studio 2012. Here is the part of the code where I get the error, in ctime. 顺便说一下,我正在使用Visual Studio 2012.这是我在ctime中得到错误的代码的一部分。 If someone can help me overcome this error, I would be glad. 如果有人能帮助我克服这个错误,我会很高兴。

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

如果您确定代码中没有安全问题,可以通过#pragma warning(disable : 4996)禁用此功能。

If you look at the description of ctime you will note: 如果你看一下ctime的描述,你会注意到:

This function 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. 另外,它修改了可以与gmtime和localtime共享的静态tm对象 POSIX marks this function obsolete and recommends strftime instead. POSIX标记此功能已过时,建议使用strftime。

The behavior may be undefined for the values of time_t that result in the string longer than 25 characters (eg year 10000) 对于导致字符串长度超过25个字符(例如10000年)的time_t值, 行为可能未定义

... that's a lot of things to worry about. ......这是很多值得担心的事情。

On the other hand, if you look at strftime : 另一方面,如果你看看strftime

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

Return value 返回值

number of bytes written into the character array pointed to by str not including the terminating '\\0' on success. 写入str指向的字符数组的字节数,不包括成功时终止的'\\ 0'。 If count was reached before the entire string could be stored, ​0​ is returned and the contents are undefined. 如果在存储整个字符串之前达到count,则返回0并且内容未定义。

All the parameters are explicit, so that you fully control the possible data races, and there is no risk of overflowing the buffer provided as well. 所有参数都是显式的,因此您可以完全控制可能的数据竞争,并且不存在溢出提供的缓冲区的风险。

This is the C-way though, and C++ introduces the <chrono> in which a specific function std::put_time can also be used to output time to a stream: 这是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';
}

which is even better since you no longer have to worry about the possible buffer overflow. 这更好,因为您不再需要担心可能的缓冲区溢出。

Yes, it should be just warning, not an error. 是的,它应该只是警告,而不是错误。 To get a simple warning instead of an error, disable SDL check in VS project (in Configuration Properties -> C/C++ -> General tab). 要获得简单警告而不是错误,请在VS项目中禁用SDL检查(在“配置属性” - >“C / C ++” - >“常规”选项卡中)。

std::ctime is not thread safe for two reasons: std::ctime不是线程安全的,原因有两个:

  • It can modify a global object of type std::tm that is shared by multiple functions. 它可以修改由多个函数共享的std::tm类型的全局对象。
  • It modifies a global char array and returns a pointer to that array. 它修改全局char数组并返回指向该数组的指针。

There is a potential for collisions if you have other threads that call std::gmtime , std::localtime , or std::ctime . 如果您有其他线程调用std::gmtimestd::localtimestd::ctime ,则可能会发生冲突。

The best thing to do is to convert that call to std::ctime to a call to std::strftime . 最好的办法是std::ctime的调用转换为对std::strftime的调用。 This is consistent with POSIX, which deems ctime to be obsolete and recommends usage of strftime in its stead. 这与POSIX一致,后者认为ctime已经过时,并建议使用strftime

vs 2017: vs 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;
}

but you will receive anyway: 但无论如何你会收到:

....cpp(31): warning C4996: 'localtime': This function or variable may be unsafe. .... cpp(31):警告C4996:'localtime':此函数或变量可能不安全。 Consider using localtime_s instead. 请考虑使用localtime_s。 To disable deprecation, use _CRT_SECURE_NO_WARNINGS. 要禁用弃用,请使用_CRT_SECURE_NO_WARNINGS。 See online help for details. 详细信息请参见在线帮助。

to prevent you can use: 防止你可以使用:

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

plain C taken partially from MSDN... old way.. 普通的C部分来自MSDN ...老方式..

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM