I've tried to research this as thoroughly as I could but cannot find where this is documented anywhere. If anyone is aware of a resource that describes this behavior that would be very helpful to me.
In the legacy software I am working on, in C++ code, the function clock() is used to get the number of cycles since the program was started. The function clock() returns a clock_t. The type clock_t is defined as a long in time.h. Also in time.h, CLOCKS_PER_SEC is defined as 1000, so clock() is returning milliseconds. Using std::numeric_limits<clock_t>::max() and doing the math, the maximum value clock() can return is reached in ~24.9 days.
The legacy code was originally written assuming the next value clock() returns after it returns the maximum value would be 0. I attempted to research this assumption and was unable to find an answer. I then ran a test and let it run for 25 days and found, to my surprise, that clock() simply continues to return its maximum value once this number is reached. Unsurprisingly, this breaks the code horribly.
The situation has already been fixed - by creating a new timer solution based on std::chrono::steady_clock, which can return nanoseconds and rolls over after ~292 years. My question here is strictly trying to find documentation of this behavior of clock() simply stopping. I would like to be able to include this in my reporting of the issue.
Thanks in advance for any info.
It depends what version of the C or C++ standard your compiler claims to implement. The behavior of clock()
is defined in the C standard, and incorporated by reference into the C++ standard.
In C11 and earlier (incorporated into C++17 and earlier), the behavior of clock()
was defined as:
If the processor time used is not available or its value cannot be represented, the function returns the value
(clock_t)(-1)
.
Overflow would correspond to "its value cannot be represented", so according to this standard, clock
should be returning -1
. Since you said clock_t
is defined as long
on your platform, which is a signed type, then -1
should not equal the maximum value, and so such behavior would be non-conformant. (However, it would if clock_t
were an unsigned type, so you might want to double check that.)
In C17 and later (corresponding to C++20 and later), this was changed to:
If the processor time used is not available, the function returns the value
(clock_t)(−1)
. If the value cannot be represented, the function returns an unspecified value.
This was probably intended to allow for the common behavior of clock
wrapping around on overflow; but it means that your implementation's unusual "saturation" behavior is conformant as well. You'd be expected to look to the implementation's own documentation for an explanation of its behavior.