View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000686 | 1003.1(2008)/Issue 7 | System Interfaces | public | 2013-05-02 03:03 | 2019-06-10 08:55 |
Reporter | dalias | Assigned To | ajosey | ||
Priority | normal | Severity | Editorial | Type | Clarification Requested |
Status | Closed | Resolution | Accepted As Marked | ||
Name | Rich Felker | ||||
Organization | musl libc | ||||
User Reference | |||||
Section | clock | ||||
Page Number | unknown | ||||
Line Number | unknown | ||||
Interp Status | --- | ||||
Final Accepted Text | 0000686:0001614 | ||||
Summary | 0000686: Application usage for clock() conflicts with normative text | ||||
Description | "If the processor time used is not available or its value cannot be represented, the function shall return the value (clock_t)-1." vs "The value returned by clock() may wrap around on some implementations. For example, on a machine with 32-bit values for clock_t, it wraps after 2147 seconds or 36 minutes." The former (aligned with ISO C) requires unrepresentable time values to result in (clock_t)-1; the latter seems to permit implementations to instead truncate the value. What's worse, if the value is truncated and clock_t is a signed type, the recommended application usage (subtracting clock_t values to measure intervals) causes the application to invoke undefined behavior via integer overflow. In particular, if the initial call to clock() returned A>0 (by virtue of some processor time having been consumed before the start of main() or the point of first measurement), and a subsequent call returned B=INT_MIN just after overflow, then the recommended practice of computing B-A invokes undefined behavior. Note that the issue is exacerbated by the XSI requirement that CLOCKS_PER_SEC be 1000000, which makes overflow on 32-bit systems the norm rather than the exception. | ||||
Desired Action | Resolve the issue in some way. This may require consulting with the ISO C committee since it seems that the path of codifying existing practice would conflict with a strict interpretation of the C standard as written, and the latter does not reflect what would be desirable to applications. If wrapping is to be permitted, then the application usage should be updated to avoid invoking undefined behavior. At present, there is no way for applications to work around the issue because there is no way to determine the numeric limits of the clock_t type if it's a signed type, meaning there is (1) no way to predict whether subtraction will overflow, and (2) no way to convert to the corresponding unsigned type to safely perform the subtraction with modular arithmetic. (Conversion to a larger unsigned type like uintmax_t will yield the wrong results.) I see several possible solutions: 1. Defining limit macros for clock_t. 2. Defining a new type uclock_t that's the corresponding unsigned type (possibly the same on implementations where clock_t itself is unsigned). 3. Requiring clock_t to be unsigned if it can wrap. (But this conflicts with existing practice on some implementations, and the implementors are reportedly unwilling to change this due to C++ ABI/name-mangling compatibility issues and possibly other issues.) | ||||
Tags | c99, tc2-2008 |
related to | 0000703 | Closed | 1003.1(2013)/Issue7+TC1 | Add errno values for clock |
|
At page 665 line 22541 section clock, insert a new first paragraph in the APPLICATION USAGE section: In programming environments where clock_t is a 32-bit integer type and CLOCKS_PER_SEC is one million, clock() will start failing in less than 36 minutes of processor time for signed clock_t, or 72 minutes for unsigned clock_t. Applications intended to be portable to such environments should use times() instead (or clock_gettime() with CLOCK_PROCESS_CPUTIME_ID, if supported). At page 665 line 22545 section clock, delete: The value returned by clock() may wrap around on some implementations. For example, on a machine with 32-bit values for clock_t, it wraps after 2147 seconds or 36 minutes. At page 665 line 22552 section clock, add clock_getres() and times() to the SEE ALSO list. |
|
I'm not opposed to this change, but it's definitely not codifying existing practice (which is to wrap), and it also makes the clock() interface rather useless on 32-bit systems. It would be nice if clock_gettime could be recommended instead of times as the alternative, since times potentially has the same issue as clock, but it seems CLOCK_CPUTIME_CLOCKID is still not mandatory. |
|
We are constrained by the C Standard here. Implementations where clock() wraps do not conform to the C Standard. (And if they claim to conform, they have a bug.) I have updated 0000686:0001614 to mention clock_gettime(). |
|
Discussed by C committee in Chicago meeting:
|
Date Modified | Username | Field | Change |
---|---|---|---|
2013-05-02 03:03 | dalias | New Issue | |
2013-05-02 03:03 | dalias | Status | New => Under Review |
2013-05-02 03:03 | dalias | Assigned To | => ajosey |
2013-05-02 03:03 | dalias | Name | => Rich Felker |
2013-05-02 03:03 | dalias | Organization | => musl libc |
2013-05-02 03:03 | dalias | Section | => clock |
2013-05-02 03:03 | dalias | Page Number | => unknown |
2013-05-02 03:03 | dalias | Line Number | => unknown |
2013-05-16 15:45 | nick | Tag Attached: c99 | |
2013-05-17 11:43 | geoffclare | Note Added: 0001614 | |
2013-05-17 14:03 | dalias | Note Added: 0001615 | |
2013-05-17 16:05 | geoffclare | Note Edited: 0001614 | |
2013-05-17 16:07 | geoffclare | Note Added: 0001616 | |
2013-05-23 15:59 | msbrown | Tag Attached: tc2-2008 | |
2013-05-23 16:00 | msbrown | Interp Status | => --- |
2013-05-23 16:00 | msbrown | Final Accepted Text | => 0000686:0001614 |
2013-05-23 16:00 | msbrown | Status | Under Review => Resolved |
2013-05-23 16:00 | msbrown | Resolution | Open => Accepted As Marked |
2013-06-13 16:26 | nick | Relationship added | related to 0000703 |
2014-04-10 15:02 | nick | Note Added: 0002219 | |
2019-06-10 08:55 | agadmin | Status | Resolved => Closed |