在RTL8710上,localtime()缩短了460,000年

时间:2018-11-24 14:11:18

标签: c embedded localtime

我正在使用RTL8710(运行rustl8710,但是就这个问题而言,这是无关紧要的,因为我正在谈论的所有代码都是C代码)。 RTL8710具有用于系统某些部分的专有库,包括localtime

但是,localtime似乎以这样的方式使用约有46万年(摘自the included NTP implementation):

long current_sec = 1543067026;
struct tm current_tm = *(localtime(&current_sec));

这将返回以下结构:

{tm_sec = 51, 
 tm_min = 36, 
 tm_hour = 15, 
 tm_mday = 25, 
 tm_mon = 8, 
 tm_year = -458682, 
 tm_wday = 2, 
 tm_yday = 267, 
 tm_isdst = -1515870811}

显然这是不正确的,应该接近格林尼治标准时间2018年11月24日13:52:04。不过,这不是随机的,因为时间似乎总是相差约2小时零几分钟。

这里唯一值得注意的是代码使用默认的系统头文件time.hstring.h(在我的情况下,它们来自Ubuntu 18.10,在我的情况下为64位)。

我不知道RealTek真正在使用什么stdlib库,但是从调试信息(newlib/libc/time/lcltime.c)来看,我猜它是newlib的(修改版本)。

1 个答案:

答案 0 :(得分:5)

代码使用了错误的类型,导致未定义的行为。 1

// long current_sec = 1543067026;
time_t current_sec = 1543067026;
struct tm current_tm = *(localtime(&current_sec));

更好的代码将在取消引用之前测试localtime()返回值。

struct tm *p = localtime(&current_sec);
if (p) {
  struct tm current_tm = *p;
  ...

1 通过以下操作可以证明类型宽度错误。

int main() {
  long current_sec = 1543067026;
  struct tm current_tm = { .tm_sec = 51, .tm_min = 36, .tm_hour = 15, //
      .tm_mday = 25, .tm_mon = 8, .tm_year = -458682, //
      .tm_wday = 2, .tm_yday = 267, .tm_isdst = -1515870811 };

  time_t t = mktime(&current_tm);
  printf("%16lx\n%16llx\n", current_sec, (unsigned long long) t);
}

输出

        5bf95592
fffff2d55bf9a9f3
        ^^^^

许多位排成一行。我怀疑较高的位差异是由于local_time()引用了垃圾位,而较低的位归因于极端计算,OP非同步发布代码和声称的输出,或者我和OP的标准库之间的差异。尽管time_t没有时区,但是我和OP的时区差异导致locatime()/mktime()差异。