Linux 系统调用 time() 在错误时返回 ((time_t) -14)
Linux system call time() is returning ((time_t) -14) on error
手册页 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() 在我的系统上 returning -14 而不是 -1。我完全被难住了。莫名其妙,甚至。
我怀疑任何人都可以重现这个问题,但是有人知道为什么我会出现这种行为吗?如果是这样,我很好奇!
编辑:我知道时间并没有取消引用我传递给它的错误指针,因为这会使程序崩溃。并且手册页确实说它应该 return -1 并且如果地址不可访问则设置 errno 。 EFAULT 是 14,但不是 returning -EFAULT not what time() is defined as doing here?
根据文档 time(2)
:
time_t time(time_t *t);
If t is non-NULL, the return value is also stored in the memory pointed to by t.
在您的调用中,您传递了一些随机地址 0xabad1dea
。你很幸运,它只返回 -14 而没有做更糟糕的事情。传递 NULL 或变量的地址。
至少有 3 个不同的地方记录了 time()
函数的行为。
The time
function returns the implementation’s best approximation to
the current calendar time. The value (time_t)(-1)
is returned if the
calendar time is not available. If timer
is not a null pointer, the
return value is also assigned to the object it points to.
标准中的其他措辞清楚地表明传递无效参数(这就是您正在做的)具有未定义的行为。 time()
需要处理空指针,但不是无效指针。
Upon successful completion, time() shall return the value of time.
Otherwise, (time_t
)-1 shall be returned.
不允许当前时间或 (time_t)(-1)
以外的结果。另一方面,POSIX 也表示:
The functionality described on this reference page is aligned with the
ISO C standard. Any conflict between the requirements described here
and the ISO C standard is unintentional. This volume of POSIX.1-2008
defers to the ISO C standard.
这可能意味着 time()
带有无效参数的行为是未定义的,就像在 C 中一样。
Linux 手册页说:
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.
它还明确表示,如果“t
指向您的可访问地址 space 之外”,则 errno
设置为 EFAULT
。因此它定义了标准未定义行为的情况下的行为,这对于实现来说是完全有效的事情。
奇怪的是它 returns -14
(-EFAULT
) 而不是将 errno
设置为 EFAULT
。返回取反的 errno
值是 Linux 内核 中函数 的常见约定。 C 运行时中的包装器通常会否定 return 值并使用它来设置 errno
,将 return 值设置为 -1
(或为特定功能)。这就是我希望在这里发生的事情。
另一件奇怪的事情:在我的系统上(Linux Mint 17,x86_64),像您一样使用无效指针调用 time()
导致我的程序因分段错误而死.
我怀疑您的系统存在错误(有一个特别简单的解决方法:不要那样做)。
更新: 我想到了另一种可能性。您的 printf
调用不正确,或者至少是不可移植的。您正在使用 "%lld"
格式打印 time_t
值,这需要类型为 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
和 long long
的大小是多少?转换参数会改变行为吗?
手册页 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() 在我的系统上 returning -14 而不是 -1。我完全被难住了。莫名其妙,甚至。
我怀疑任何人都可以重现这个问题,但是有人知道为什么我会出现这种行为吗?如果是这样,我很好奇!
编辑:我知道时间并没有取消引用我传递给它的错误指针,因为这会使程序崩溃。并且手册页确实说它应该 return -1 并且如果地址不可访问则设置 errno 。 EFAULT 是 14,但不是 returning -EFAULT not what time() is defined as doing here?
根据文档 time(2)
:
time_t time(time_t *t);
If t is non-NULL, the return value is also stored in the memory pointed to by t.
在您的调用中,您传递了一些随机地址 0xabad1dea
。你很幸运,它只返回 -14 而没有做更糟糕的事情。传递 NULL 或变量的地址。
至少有 3 个不同的地方记录了 time()
函数的行为。
The
time
function returns the implementation’s best approximation to the current calendar time. The value(time_t)(-1)
is returned if the calendar time is not available. Iftimer
is not a null pointer, the return value is also assigned to the object it points to.
标准中的其他措辞清楚地表明传递无效参数(这就是您正在做的)具有未定义的行为。 time()
需要处理空指针,但不是无效指针。
Upon successful completion, time() shall return the value of time. Otherwise, (
time_t
)-1 shall be returned.
不允许当前时间或 (time_t)(-1)
以外的结果。另一方面,POSIX 也表示:
The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of POSIX.1-2008 defers to the ISO C standard.
这可能意味着 time()
带有无效参数的行为是未定义的,就像在 C 中一样。
Linux 手册页说:
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.
它还明确表示,如果“t
指向您的可访问地址 space 之外”,则 errno
设置为 EFAULT
。因此它定义了标准未定义行为的情况下的行为,这对于实现来说是完全有效的事情。
奇怪的是它 returns -14
(-EFAULT
) 而不是将 errno
设置为 EFAULT
。返回取反的 errno
值是 Linux 内核 中函数 的常见约定。 C 运行时中的包装器通常会否定 return 值并使用它来设置 errno
,将 return 值设置为 -1
(或为特定功能)。这就是我希望在这里发生的事情。
另一件奇怪的事情:在我的系统上(Linux Mint 17,x86_64),像您一样使用无效指针调用 time()
导致我的程序因分段错误而死.
我怀疑您的系统存在错误(有一个特别简单的解决方法:不要那样做)。
更新: 我想到了另一种可能性。您的 printf
调用不正确,或者至少是不可移植的。您正在使用 "%lld"
格式打印 time_t
值,这需要类型为 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
和 long long
的大小是多少?转换参数会改变行为吗?