繁体   English   中英

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

[英]How to get the current time in c++ in a “ Safe ” way

我对 C++ 并不陌生,但我大多只使用最基本的标准库功能,如<iostream><vector><map>等。

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

不要误会我的意思,我在 StackOverflow 和 Google 中看到了很多打发时间的方法,但根据 Visual Studio,它们都不是“安全的”。 例如,当我使用asctime()ctime()时,我收到此错误:

['ctime':这个 function 或变量可能不安全。 考虑改用 ctime_s。 要禁用弃用,请使用 _CRT_SECURE_NO_WARNINGS。 详情请参见在线帮助]。

但是当我尝试用好方法并使用安全版本时,我发现它们更加复杂,例如这是ctime() function:

ctime(const time_t *const_time)

ctime_s()相比:

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

再次查看互联网并没有帮助我,所以我在这里,问你们如何获取当前时间,我的意思是像10:20或类似的时间,使用“安全”方法。

现代 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+ 编码器(a) ,那么建议您转到<chrono>

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

如果您可以开始使用这些,您将永远不再需要旧版 C 的东西:-)


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

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

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

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

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

如果你知道你的使用模式(包括你使用的任何第三方的东西),你可以轻松地使用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以便更好地控制 output 格式(例如 '"yyyy-mm-dd hh:mm:ss"`),因此可以保证生成的字符串适合缓冲区) .


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

asctime()ctime()函数是“不安全的”,因为它们返回指向 static 缓冲区的指针,根据实现,这些缓冲区可能是线程安全的,也可能不是线程安全的,如果它们不是线程安全的,那么它们可能会被其他线程覆盖在你有机会使用它们之前。

“更安全”的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...

暂无
暂无

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

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