localtime vs localtime_s 和适当的输入参数

Posted

技术标签:

【中文标题】localtime vs localtime_s 和适当的输入参数【英文标题】:localtime vs localtime_s and appropriate input arguments 【发布时间】:2013-01-01 10:55:15 【问题描述】:
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );

这将返回:警告 C4996:“本地时间”:此函数或变量可能不安全。考虑改用 localtime_s。

time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime_s ( &rawtime );

当我将 localtime 更改为 localtime_s 时,我得到:错误 C2660: 'localtime_s' : function does not take 1 arguments

这是我认为第一块代码中发生的事情:

创建一个空的 time_t 变量。 创建指向在 ctime 中定义的 timeinfo 的指针 将 rawtime 写入 rawtime 引用

将原始时间转换为对行人有意义的东西

    我说的对吗? localtime_s 需要什么第二个输入参数? 如果我忽略整个本地时间安全问题,可能会发生什么最糟糕的情况。

【问题讨论】:

是的,我立即找到了这个:msdn.microsoft.com/en-us/library/a442x3ye(v=vs.80).aspx 但我还不明白如何解释这些模板/泛型?方法的描述。就像我不理解一般形式的 wiki 数学文章的语法/符号一样。 struct tm* _tm 和 const time_t *time 就我真正告诉方法的内容而言对我没有任何意义......尽管我希望它这样做。 是的,我也有一些。 【参考方案1】:

localtime 返回一个指向静态分配的struct tm 的指针。

使用 localtime_s,您传入一个指向 struct tm 的指针,localtime_s 将其结果数据写入其中,因此您的代码将从:

struct tm *timeinfo;
timeinfo = localtime(&rawtime);

类似于:

struct tm timeinfo;
localtime_s(&timeinfo, &rawtime);

这样,它会写入您的缓冲区,而不是拥有自己的缓冲区。

【讨论】:

通过这些更改,我得到了以下错误:错误 C2679:二进制“=”:未找到采用“errno_t”类型右手操作数的运算符(或没有可接受的转换)1> c :\Program Files\Microsoft Visual Studio 10.0\VC\include\wchar.h(1120): 可能是 'tm &tm::operator =(const tm &)' 1> 同时尝试匹配参数列表 '(tm, errno_t )' 错误 C2664: 'strftime' : 无法将参数 4 从 'tm' 转换为 'const tm *' 1> 没有可以执行此转换的用户定义转换运算符,或者无法调用该运算符 @ProGirlXOXO:这显然发生在你​​上面没有显示的代码中,但这可能是因为timeinfo 现在是一个struct tm 而不是一个指针,所以在其他函数使用它的地方,你'需要将timeinfo 更改为&timeinfo 这一行: &timeinfo = localtime_s ( &timeinfo, &rawtime );给出此错误:错误 C2440: '=' : cannot convert from 'errno_t' to 'tm *' @ProGirlXOXO:重读答案。 localtime 返回一个指向 struct tm 的指针 -- localtime_s not (它返回一个错误号来告诉您请求的转换是否成功)。【参考方案2】:

localtime_s 只是本地时间函数的微软实现,您可以安全地继续使用locatime,因为它符合 C++ ISO 标准并且只有微软将其标记为“已弃用”。 localtime 函数本身在 C++ 世界中根本不被弃用。

localtime_sreference 表示应该将这些参数传递给它:

_tm 
Pointer to the time structure to be filled in.
 time 
Pointer to the stored time.

【讨论】:

FWIW,POSIX 标准更正函数是localtime_r。工作原理完全相同,只是两个参数的顺序颠倒了。 localtime_s 是自 C11 以来standard 的一部分。 @Pietro 仅作为optional Annex K 的一部分,它事实上仅由Microsoft(较差地)实现。每Field Experience With Annex K — Bounds Checking Interfaces:“由于与规范有大量偏差,微软的实现不能被认为是符合或可移植的。” @AndrewHenle - 感谢您指出这一点。只需阅读 cppreference:“Microsoft CRT 中 localtime_s 的实现与 C 标准不兼容,因为它颠倒了参数顺序。”【参考方案3】:

正如Lightness Races in Orbit 所指出的,localtime 和其他几个时间函数一样不是线程安全的。我想了解更多有关该主题的信息,我找到了a relevant blog post,并对此进行了粗略的解释。

下面的引用解释了为什么localtime不是线程安全的:

[...] localtime 返回指向静态缓冲区 (std::tm*) 的指针。另一个线程可以调用该函数,并且可以在第一个线程完成读取 struct std::tm* 的内容之前覆盖静态缓冲区。

【讨论】:

以上是关于localtime vs localtime_s 和适当的输入参数的主要内容,如果未能解决你的问题,请参考以下文章

C语言编程函数localtime_s在VS 2020中写的程序参数错误,参数怎么写?

Windows 上 localtime_s() 多线程性能不佳的解决方法

C语言关于localtime_s()和asctime_s()两个函数的用法。

当我使用模板时,未在此范围GCC Linux环境中声明strerror_s,strcpy_s,localtime_s,sprintf_s?

打印日志的时候显示毫秒

用C11获取时间日期