Переполнение преобразований std :: chrono time_t? - PullRequest
2 голосов
/ 27 февраля 2020

Мой пример кода:

time_t time_tee = 253402210800;
auto tp = std::chrono::system_clock::from_time_t(time_tee);
time_t tee2 = std::chrono::system_clock::to_time_t(tp);
std::cout << tee2 << std::endl;

Ожидание: Выход 2534022108 Выход: -4852206231

time_t 64-битное, поэтому переполнение не должно быть.

Что Какое переполнение я запускаю здесь?

Живая демоверсия
Отлично работает на MSV C

Ответы [ 2 ]

2 голосов
/ 27 февраля 2020

glibc system_clock::duration использует chrono::nanoseconds для сохранения момента времени. chrono::nanoseconds - это int64_t.

Поскольку:

253402210800 seconds = 253402210800000000000 nanoseconds
INT64_MAX            = 922337203685477580

вычисление переполняется на glib c.

Не знаю см. все ограничения на system_clock::rep в стандартном проекте , за исключением того, что он должен быть подписан.

Какой тип переполнения я запускаю здесь?

Подписанное переполнение происходит внутри system_clock::from_time_t(time_tee);, когда 253402210800 умножается на 1000000000 при приведении time_t к system_clock::duration внутри time_point_cast<system_clock::duration>. Я думаю, что это будет точно внутри __duration_cast_impl.

Я думаю, вы должны защитить от переполнения с помощью чека, например:

static_assert(
    std::chrono::duration_cast<std::chrono::seconds>
    (std::chrono::system_clock::duration::max()).count() > 253402210800
);
2 голосов
/ 27 февраля 2020

Проблема заключается во временном разрешении system_clock.

Этот код:

#include <chrono>
#include <iostream>

int main()
{
    using std::chrono::system_clock;
    time_t time_tee = 253402210800;
    auto tp = system_clock::from_time_t(time_tee);
    time_t tee2 = system_clock::to_time_t(tp);
    std::cout << time_tee << std::endl;
    std::cout << tee2 << std::endl;
    std::cout << system_clock::period::num << std::endl;
    std::cout << system_clock::period::den << std::endl;

    return 0;
}

Вкл. MSV C отпечатки :

253402210800
253402210800
1
10000000

On G CC или clang prints :

253402210800
-4852206231
1
1000000000

Итак, как вы можете видеть, G CC и Clang используют system_cloc в 100 раз большее разрешение. Обратите внимание, что это разрешение также лучше, чем time_t предложений, а стоимость более ограничена по времени.

...