小心 timeval 和 timespec 不小心溢出了
来源:互联网 发布:mac下载文件夹不见了 编辑:程序博客网 时间:2024/04/20 10:14
timeval 和 timespec 都是 POSIX 的秒以下时间类型,都是一个两个成员的结构,第一个成员是秒数,第二个成员则分别是微秒和纳秒。
之所以用这么个结构,是因为如果直接存储毫秒微秒或者纳秒,32位的整数根本放不下。
要说为什么不像 windows 下那样用 64 位的整数类型,我也觉得很好,但是十年前的编译器多数都没有提供 64 位的整数类型。
至于为什么有这两个用途差不多的时间类型,我也不知道。
前几天调试程序,发现带超时的等待偶尔会返回 EINVAL,也就是无效参数。
int GetResult(Result *result, const struct timeval *timeout)
{
struct timespec abstime;
struct timeval now;
int ret = 0;
{
struct timespec abstime;
struct timeval now;
int ret = 0;
pthread_mutex_lock(&mutex_);
gettimeofday(&now, NULL);
abstime.tv_sec = now.tv_sec + timeout->tv_sec;
abstime.tv_nsec = 1000 * ();
abstime.tv_sec = now.tv_sec + timeout->tv_sec;
abstime.tv_nsec = 1000 * ();
while (queue_.empty() && ret != ETIMEDOUT)
ret = pthread_cond_timedwait(&cond_, &mutex_, &abstime);
ret = pthread_cond_timedwait(&cond_, &mutex_, &abstime);
...
}
}
问题在这里:当 now.tv_usec + timeout->tv_usec >= 1000000 时,abstime.tv_nsec 也就大于或者等于 10^9 了,直接传给 pthread_condwait 的时候,被认为是无效时间,直接返回 EINVAL 了。出错的概率等于传入的 timeout 中 tv_usec 折合的秒数。
这时候应该进位,秒数加一:
if (abstime.tv_nsec >= BILLION)
{
++abstime.tv_sec;
{
++abstime.tv_sec;
++abstime.tv_nsec %= BILLION;
}
}
如果这样写,传入的 timeval 有问题也能修正,可以更安全一些,这时候应该修正还是报错,这是个哲学问题。
const long BILLION = 1000000000;
if (abstime.tv_nsec >= BILLION)
{
abstime.tv_sec += abstime.tv_nsec / BILLION;
abstime.tv_nsec %= BILLION;
}
此时的判断也可以去掉,如果传入的 timeout 的 tv_usec 比较小,则溢出的概率较低,加上这个判断可以减少后面的除法开销。总之这不再是bug,是个小问题了。
if (abstime.tv_nsec >= BILLION)
{
abstime.tv_sec += abstime.tv_nsec / BILLION;
abstime.tv_nsec %= BILLION;
}
此时的判断也可以去掉,如果传入的 timeout 的 tv_usec 比较小,则溢出的概率较低,加上这个判断可以减少后面的除法开销。总之这不再是bug,是个小问题了。
- 小心 timeval 和 timespec 不小心溢出了
- timeval和timespec转换
- 不小心闯红灯了
- struct timeval 和 struct timespec
- struct timeval 和 struct timespec
- struct timeval 和 struct timespec
- struct timeval 和 struct timespec
- struct timespec 和 struct timeval
- struct timespec 和 struct timeval
- struct timeval 和 struct timespec
- struct timespec 和 struct timeval
- struct timespec 和 struct timeval
- struct timespec 和 struct timeval
- struct timespec 和 struct timeval
- struct timespec 和 struct timeval
- 不小心过了网络工程师。
- 不小心闪了腰
- 不小心扭伤了脚
- C# WinForm中将Form显示在Panel中(C#)
- Head First C# 中文版 第九章 读写文件 page385
- 洛克菲勒给儿子的信:现在就去做
- Oracle failsafe与rac两者之间的不同之处
- 野指针概念
- 小心 timeval 和 timespec 不小心溢出了
- 理解ThreadLocal
- Linux图形界面与字符界面转换
- 71
- ははうえさま/亲爱的妈妈
- 巨人网络史玉柱:做最成熟的老板
- C# WinForm实现气泡提示效果
- 函数指针、指针函数 概念
- vs工程设置造成的问题