如何以“安全”的方式获取 C++ 中的当前时间

How to get the current time in c++ in a " Safe " way

我不是 C++ 的新手,但我主要只使用最基本的标准库功能,如 <iostream><vector><map>

现在,我正在开发一款简单的游戏,并且正在开发一个记录器 class,但我无法获取当前时间。

不要误会我的意思,我在 Whosebug 和 Google 中看到了很多获取时间的方法,但根据 [,其中 none 是 "safe" =39=].例如,当我使用 asctime()ctime() 时,出现此错误:

['ctime': This function or variable may be unsafe. Consider using ctime_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details].

但是当我尝试以好的方式使用安全版本时,我发现它们更加复杂,例如这是 ctime() 函数:

ctime(const time_t *const_time)

ctime_s()相比:

ctime_s(char *const _Buffer, const size_t _SizeinBytes,const time_t *const _Time)

再次在互联网上查找对我没有帮助,所以我在这里向大家询问如何获取当前时间,而时间我的意思是 10:20 或类似的东西,使用 "safe" 方法。

现代 C++ 有 <chrono> header 用于时间提取和操作,一旦你理解它,它比 很多 遗留的 C 东西:

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

int main() {
    auto start = std::chrono::system_clock::now();
    auto legacyStart = std::chrono::system_clock::to_time_t(start);
    std::cout << std::ctime(&legacyStart) << '\n';
}

这可以用于多种方式,包括(如图所示)输出日期的字符串表示形式。我意识到对于这个简单的案例来说,这不是 必需的,但是如果你不想被称为 C+ 编码器[=52],建议你转到 <chrono> =](a).

如果您可以使用 C++20,则尤其如此,因为该迭代包括日历功能(用于日期)和 time-of-day 功能(用于将自午夜以来的持续时间拆分为单独的组件,例如小时、分钟和秒)。

如果你能开始使用它们,你将再也不需要遗留的 C 东西了:-)


关于这是否不安全,我认为微软在做出这个决定时经常对编码人员造成伤害。我实际上关闭了这些警告,因为我知道涉及的风险,并且知道如何避免问题。

无论如何,我相信我在某些时候读到 s 是为了安全而不是安全,因为某些替换功能 不是 安全的,如果你,例如,将错误的长度传递给它们:

char dest[10];
strcpy_s(dest, 100, "13 characters");

现在毫无疑问,有些人会说这是编码人员的错,因为他们应该知道自己在做什么,但是对于所谓的 不安全 函数也可以提出同样的论点。

ctime() 的具体问题是它允许 return 内部缓冲区的地址,下次调用它时可能会被覆盖(而这个 可能 还包括另一个在您完成之前调用它的线程。

如果您知道自己的使用模式(包括您使用的任何 third-party 东西),您可以轻松使用 ctime() 而不会出现问题。

但是, 并不难,在这种情况下,使用更安全的变体,例如:

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

int main() {
    auto start = std::chrono::system_clock::now();
    auto legacyStart = std::chrono::system_clock::to_time_t(start);
    char tmBuff[30];
    ctime_s(tmBuff, sizeof(tmBuff), &legacyStart);
    std::cout << tmBuff << '\n';
}

虽然您可能想考虑使用strftime以便更好地控制输出格式(例如'"yyyy-mm-dd hh:mm:ss"`),因此保证结果字符串适合缓冲区)。


(a) 从未 完全 完全从 C 过渡到 C++ 的奇怪品种:-)

asctime()ctime() 函数是 "unsafe" 因为它们 return 指向静态缓冲区的指针,根据实现的不同,这些缓冲区可能是也可能不是线程安全的,并且如果它们不是线程安全的,那么它们可能会在您有机会使用它们之前被其他线程覆盖。

"more secure" asctime_s()ctime_s() 函数写入您必须提供的预分配缓冲区,例如:

time_t now = time(NULL);
//char *str = asctime(localtime(&now));
tm now_tm = {};
char str[26] = {};
localtime_s(&now_tm, &now);
asctime_s(str, 26, &now_tm);
// use str as needed...
time_t now = time(NULL);
//char *str = ctime(&now);
char str[26] = {};
ctime_s(str, 26, &now);
// use str as needed...