手册页man 2 time
说:
SYNOPSIS
#include <time.h>
time_t time(time_t *t);
RETURN VALUE
On success, the value of time in seconds since the Epoch is returned. On error,
((time_t) -1) is returned, and errno is set appropriately.
ERRORS
EFAULT t points outside your accessible address space.
我有一个简单的测试设置,试图强制该函数的错误 - 应该是最直接的事情:
time_t *ptr = (time_t *) 0xabad1dea;
time_t secs = time(ptr);
if (secs == ((time_t) -1)) /* Not caught */
exit(EXIT_FAILURE);
printf("Number of seconds since the Epoch: %lld\n", secs);
printf("It should return ((time_t) -1) on error: %lld\n", (time_t) -1);
secs = *ptr; /* This *does* segfault */
出于某种原因,time()在我的系统上返回-14而不是-1。我完全难过了。困惑,甚至。
我怀疑任何人都可以重现这个问题,但有人在那里知道为什么我可能会得到这种行为吗?如果是这样,我非常好奇!
编辑:我知道时间不会取消引用我传递它的错误指针,因为它会导致程序崩溃。手册页确实说它应该返回-1并设置errno,如果地址不可达。 EFAULT是14,但是没有返回-EFAULT 不什么时间()被定义为在这里做?答案 0 :(得分:3)
根据文档time(2)
:
time_t time(time_t * t);
如果t为非NULL,则返回值也存储在t指向的内存中。
在通话中,您传递的是随机地址0xabad1dea
。你很幸运,它只返回-14并且没有做更糟糕的事情。传递NULL或变量的地址。
答案 1 :(得分:1)
至少有3个差异点,其中记录了time()
函数的行为。
time
函数返回实现的最佳近似值 当前的日历时间。如果是,则返回值(time_t)(-1)
日历时间不可用。如果timer
不是空指针,则 返回值也分配给它指向的对象。
标准中的其他措辞清楚地表明,传递无效参数(这是您正在做的事情)具有未定义的行为。 <{1}}需要处理空指针,但不能处理无效指针。
成功完成后,时间()将返回时间值。 否则,(
time()
) - 1将被退回。
不允许除当前时间或time_t
以外的结果。另一方面,POSIX也说:
此参考页面上描述的功能与 ISO C标准。此处描述的要求之间存在任何冲突 而ISO C标准是无意的。本卷POSIX.1-2008 遵循ISO C标准。
可以暗示(time_t)(-1)
带有无效参数的行为未定义,就像在C中一样。
Linux手册页说:
成功时,返回自Epoch以来的秒数。 出错时,返回((time_t)-1),并正确设置errno。
如果&#34; time()
指向您可访问的地址空间&#34;之外,它还明确表示errno
设置为EFAULT
。因此,它定义了行为未被标准定义的情况下的行为,并且这对于实现来说是完全有效的。
奇怪的是,它返回 t
(-14
),而不是将-EFAULT
设置为errno
。返回否定的EFAULT
值是Linux内核中函数的常见约定。 C运行时中的包装器通常会否定该返回值并使用它来设置errno
,将返回值设置为errno
(或者为特定函数定义的错误值)。这就是我期望在这里发生的事情。
另一个奇怪的事情:在我的系统(Linux Mint 17,x86_64)上,使用无效指针调用-1
会导致我的程序死于分段错误。
我怀疑你的系统存在一个错误(特别容易的解决方法:不要这样做)。
更新:另一种可能性发生在我身上。您的time()
来电不正确,或至少不便携。您以printf
格式打印time_t
值,这需要"%lld"
类型的参数。您应该将参数强制转换为long long
:
long long
如果printf("Number of seconds since the Epoch: %lld\n",
(long long)secs);
printf("It should return ((time_t) -1) on error: %lld\n",
(long long)((time_t) -1));
和time_t
在您的系统上具有相同的宽度,则可能在没有强制转换的情况下工作(但您仍应添加它们)。但如果long long
比time_t
更窄,long long
可能会从相邻内存中获取迷路printf
值。
系统中-14
和time_t
的大小是多少?强制转换参数会改变行为吗?