[OT] The Usual Arithmetic Confusions
Siarhei Siamashka
siarhei.siamashka at gmail.com
Mon Feb 21 05:40:58 UTC 2022
On Friday, 18 February 2022 at 10:13:42 UTC, Timon Gehr wrote:
> On 18.02.22 09:05, Walter Bright wrote:
>> If you've got an array length longer than int.max,
>
> Seems I likely won't have that (compiled with -m32):
>
> ```d
> void main(){
> import core.stdc.stdlib;
> import std.stdio;
> writeln(malloc(size_t(int.max)+1)); // null (int.max works)
> auto a=new ubyte[](int.max); // out of memory error
> }
> ```
This is either an OS configuration issue (you are exceeding a
per-process limit for one of the resources) or maybe there could
be indeed some large arrays handling bugs in the D library.
Dealing with utilizing as much memory as possible on 32-bit
systems is already an ancient history. Server admins used to
tweak various things, such PAE or 3.5G/0.5G user/kernel address
space split, etc. But now none of this really matters anymore,
because all memory hungry servers moved to 64-bit hardware a long
time ago.
And before that, there used to be such things as EMS and himem on
ancient 16-bit MS-DOS systems to use as much memory as possible
by applications. But modern D compilers even can't generate
16-bit code and nobody cares today. I guess, some or even many
people in this forum were born after this stuff became obsolete.
Personally I'm not going to miss anything if sizes of arrays
change to use a signed type and int.max (or ssize_t.max) becomes
the official array size limit on 32-bit systems.
> Most of that is not too helpful as it's not exposed by the
> language. (At least in D, signed arithmetic actually has 2-s
> complement semantics, but the hardware has some features to
> make dealing with 2-s complement convenient that are not really
> exposed by the programming language.)
The hardware only provides the flags register, which can be
checked for overflows after arithmetic operations. This
functionality is provided by
https://dlang.org/phobos/core_checkedint.html in D language, but
I wouldn't call it convenient. The flags checks in assembly are
not convenient either.
> In any case, I can get it right, the scenario I had in mind is
> competent programmers having to spend time debugging a weird
> issue and then ultimately fix some library dependency that
> silently acquires funky behavior once the data gets a bit
> bigger than what's in the unit tests because the library
> authors blindly followed a `ptrdiff_t` recommendation they once
> saw in the forums.
I still think that support for trapping arithmetic overflows at
runtime is a reasonable solution. It can catch a lot of bugs,
which are very hard to debug using other methods.
For example, there are not too many signed arithmetic overflows
in phobos. Passing the phobos unit tests with signed overflows
trapping enabled (the "-ftrapv" option in GDC) only requires some
minor patches in a few places:
https://github.com/ssvb/gcc/commits/gdc-ftrapv-phobos-20220209
Most of the affected places in phobos are already marked with
cautionary comments ("beware of negating int.min", "there was an
overflow bug, here's a link to bugzilla", etc.). A history of
blood and suffering is recorded there.
Some people may think that (signed) arithmetic overflows being
defined to wraparound is a useful feature of the D language and
some software may rely on it for doing something useful. But I
don't see any real evidence of that. Most of the silent
arithmetic overflows look like just yet undetected and
undesirable bugs. The next step is probably to see how many
changes are needed in the compiler frontend code to make it
"-ftrapv" compatible too.
But again, the problem is not technical at all. The problem is
that too many people are convinced that silent wraparounds are
good and nothing needs to be changed or improved. Or that
rudimentary VRP checks at compile time are sufficient.
More information about the Digitalmars-d
mailing list