std :: chrono :: duration_cast - GCC实现是否被窃听?

Val*_*84 6 c++ gcc std c++-chrono

我想我在std :: chrono :: duration_cast的GCC实现中发现了一个错误.有谁可以请证实我这个?

测试代码:

using Ticks = std::chrono::duration<long long, std::ratio_multiply<std::chrono::nanoseconds::period, std::ratio<100>>>;

using dur = typename std::chrono::system_clock::duration;

int main() 
{

    std::chrono::time_point<std::chrono::system_clock> earliest {std::chrono::duration_cast<dur>(
    std::chrono::time_point<std::chrono::system_clock, Ticks>::max().time_since_epoch())};

    auto ticks = std::chrono::time_point<std::chrono::system_clock, Ticks>::max().time_since_epoch().count();
    std::cout << "Ticks: " << ticks << "\n";
    std::cout << sizeof(earliest.time_since_epoch().count()) << "\n";
    std::cout << "Microseconds: " << earliest.time_since_epoch().count() << "\n";

    std::time_t t = std::chrono::system_clock::to_time_t(earliest);
    std::cout << "earliest:\n" << std::ctime(&t);
}
Run Code Online (Sandbox Code Playgroud)

clang 3.8的输出是:

Ticks: 9223372036854775807
8
Microseconds: 922337203685477580
earliest:
Sun Sep 14 02:48:05 31197
Run Code Online (Sandbox Code Playgroud)

GCC 7.1的输出是:

Ticks: 9223372036854775807
8
Microseconds: -100
earliest:
Thu Jan  1 00:00:00 1970
Run Code Online (Sandbox Code Playgroud)

我错了吗?

Mas*_*nes 5

这不是一个错误,你只是导致签名溢出,因此未定义的行为.实际上,您的代码依赖于平台相关的假设(系统时钟周期和代表类型),这些假设恰好在gcc测试用例中失败.

在撰写本文时,system_clockColiru的GCC环境使用了长纳秒的纳秒持续时间,而长度则具有相同的长度.

所以,当你duration_cast<system_clock::duration>一个time_point<system_clock,Ticks>::max().time_since_epoch()

你正在将每个持续numeric_limits<Ticks::rep>::max()时间为100纳秒的持续时间转换为长类型的纳秒持续时间,导致相当于numeric_limits<Ticks::rep>::max()*100明显溢出的东西(你的双补码签名实现恰好换行,导致-100;无论如何,这仍然是未定义的行为).

相反,在我的clang副本上,system_clock有一个长长度类型的微秒持续时间,导致持续时间等效ot numeric_limits<Ticks::rep>::max()/10.