Time to move std.experimental.checkedint to std.checkedint ?

tsbockman thomas.bockman at gmail.com
Wed Mar 31 09:01:39 UTC 2021


On Wednesday, 31 March 2021 at 04:49:01 UTC, Andrei Alexandrescu 
wrote:
> On 3/31/21 12:47 AM, Andrei Alexandrescu wrote:
>> On 3/31/21 12:32 AM, tsbockman wrote:
>>> On Wednesday, 31 March 2021 at 03:32:40 UTC, Andrei 
>>> Alexandrescu wrote:
>>>> On 3/30/21 7:01 PM, tsbockman wrote:
>>>>> Simply flipping compiler switches (the -ftrapv and -fwrapv 
>>>>> flags in gcc Andrei mentioned earlier) won't work, because 
>>>>> most high performance code contains some deliberate and 
>>>>> correct examples of wrapping overflow, signed-unsigned 
>>>>> reinterpretation, etc.
>>>>>
>>>>> Idiomatic Zig code (probably Ada, too) does contain this 
>>>>> information. But, the selection of "real world" open source 
>>>>> Zig code available for testing is limited right now, since 
>>>>> Zig hasn't stabilized the language or the standard library 
>>>>> yet.
>>>>
>>>> That's awfully close to "No true Scotsman".
>>>
>>> Just tossing out names of fallacies isn't really very helpful 
>>> if you don't explain why you think it may apply here.
>>
>> I thought it's fairly clear

Thank you for explaining anyway.

>> - the claim is non-falsifiable: if code is faster without
>> checks, it is deemed so on account of tricks.

I've never disputed at any point that unchecked code is, by 
nature, almost always faster than checked code - albeit often not 
by much. I haven't attributed unchecked code's speed advantage to 
"tricks" anywhere.

>> Code without checks could benefit of other, better
>> tricks, but their absence is explained by the small size of the
>> available corpus.
>
> s/Code without checks could benefit of other/Code with checks 
> could benefit of other/

While I think it is true that "better tricks" can narrow the 
performance gap between checked and unchecked code, that is not 
at all what I was talking about at all in the paragraphs you 
labeled "No true Scotsman".

Consider a C++ program similar to the following D program:

/////////////////////////////////////
module app;

import std.stdio : writeln, readln;
import std.conv : parse;

N randLCG(N)() @safe
     if(is(N == int) || is(N == uint))
{
     static N state = N(211210973);
     // "Numerical Recipes" linear congruential generator:
     return (state = N(1664525) * state + N(1013904223)); // can 
and should wrap
}

double testDivisor(N, N divisor)(const(ulong) trials) @safe
     if(is(N == int) || is(N == uint))
{
     N count = 0;
     foreach(n; 0 .. trials)
         count += (randLCG!N() % divisor) == N(0); // can, but 
should *not* wrap
     return count / real(trials);
}

void main() {
     string input = readln();
     const trials = parse!ulong(input);
     writeln(testDivisor!( int, 3)(trials));
     writeln(testDivisor!(uint, 3)(trials));
}
/////////////////////////////////////

randLCG!( int, 3) requires -fwrapv and NOT -ftrapv to work as 
intended.
randLCG!(uint, 3) works correctly no matter what.
testDivisor!( int, 3) requires -ftrapv and NOT -fwrapv to detect 
unintended overflows.
testDivisor!(uint, 3) is always vulnerable to unintended 
overflow, with or without -ftrapv.

So, neither -ftrapv nor -fwrapv causes an idiomatic C++ program 
detect unintended overflows without false positives in the 
general case. The compiler simply doesn't have enough information 
available to do so, regardless of how much performance we are 
willing to sacrifice. Instead, the source code of a C++ program 
must first be modified by a real human being to make it 
compatible with either -ftrapv or -fwrapv (which are mutually 
exclusive).

The paper you linked earlier mentions this problem: "Finally 
often integer overflows are known to be intentional or the 
programmer has investigated it and determined it to be 
acceptable. To address these use cases while still being useful 
in reporting undesired integer overflows, a whitelist 
functionality was introduced to enable users to specify certain 
files or functions that should not be checked.
...
Second, our methodology for distinguishing intentional from 
unintentional uses of wraparound is manual and subjective. The 
manual effort required meant that we could only study a subset of 
the errors..."
(See sections 5.3 and 6.1 of 
https://dl.acm.org/doi/abs/10.1145/2743019)

Idiomatic Zig code already contains the information which the 
researchers on that paper had to manually insert for all the 
C/C++ code they tested. That is why my tests were limited to Zig, 
because I don't have the time or motivation to go and determine 
whether each and every potential overflow in GCC or Firefox or 
whatever is intentional, just so that I can benchmark them with 
-ftrapv enabled.


More information about the Digitalmars-d mailing list