11

我有一个关于静态源代码分析的大项目,一切都编译成功,除了一件事。我在标题中提供了错误消息。让我感到困惑的一点是,它给出了一条错误消息,说不安全。我认为这应该只是警告,而不是错误。顺便说一句,我使用的是 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());
     }
}
4

5 回答 5

11

如果您确定代码中没有安全问题,您可以通过#pragma warning(disable : 4996).

于 2012-11-25T12:21:23.680 回答
11

如果您查看ctime的描述,您会注意到:

此函数返回指向静态数据的指针,并且不是线程安全的。此外,它还修改了可以与 gmtime 和 localtime 共享的静态 tm 对象。POSIX 将此函数标记为已过时,并推荐使用 strftime。

对于导致字符串长度超过 25 个字符(例如 10000 年)的 time_t 值,行为可能未定义

......有很多事情需要担心。

另一方面,如果您查看strftime

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

返回值

写入 str 指向的字符数组的字节数,不包括成功时的终止 '\0'。如果在可以存储整个字符串之前达到计数,则返回​0​并且内容未定义。

所有参数都是显式的,因此您可以完全控制可能的数据竞争,并且也不存在溢出提供的缓冲区的风险。

虽然这是 C 方式,但 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';
}

这更好,因为您不再需要担心可能的缓冲区溢出。

于 2012-11-25T14:36:39.137 回答
5

是的,它应该只是警告,而不是错误。要获得简单的警告而不是错误,请在 VS 项目中禁用 SDL 检查(在配置属性 -> C/C++ -> 常规选项卡中)。

于 2013-08-01T08:51:11.317 回答
4

std::ctime不是线程安全的,原因有两个:

  • 它可以修改std::tm由多个函数共享的类型的全局对象。
  • 它修改一个全局char数组并返回一个指向该数组的指针。

如果您有其他线程调用std::gmtimestd::localtime或,则可能发生冲突std::ctime

最好的办法是将调用转换std::ctime为调用std::strftime. 这与 POSIX 一致,后者认为ctime已过时并建议使用 ofstrftime代替。

于 2012-11-25T14:00:29.560 回答
1

与 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':此函数或变量可能不安全。考虑改用 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 ......旧方式..

于 2017-08-04T11:33:01.203 回答