Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
February 22, 2018 array/Array: "hard" bounds checking | ||||
---|---|---|---|---|
| ||||
Is there a D equivalent of the C++ at method? I would like to reformulate repro2.d --- void main () { import std.stdio; import std.container; import std.range; auto z = Array!char(); z.reserve(0xC000_0000); z.capacity.writeln; z.length.writeln; for (uint u = 0; u < 0xC000_0000; ++u) z.insert = 'Y'; int i = -1073741825; i.writeln; z[i] = 'Q'; z[i].writeln; } --- $ dmd -O -m32 repro2.d $ ./repro2 3221225472 0 -1073741825 Q such that it fails like the 64 bit version: $ dmd -O -m64 repro2.d $ ./repro2 3221225472 0 -1073741825 core.exception.RangeError@.../dmd2/linux/bin64/../../src/phobos/std/container/array.d(650): Range violation ---------------- ??:? _d_arrayboundsp [0x440d22] .../dmd2/linux/bin64/../../src/phobos/std/container/array.d:650 inout pure nothrow ref @nogc @safe inout(char) std.container.array.Array!(char).Array.opIndex(ulong) [0x43bb0f] repro2.d:14 _Dmain [0x43afff] |
February 22, 2018 Re: array/Array: "hard" bounds checking | ||||
---|---|---|---|---|
| ||||
Posted in reply to kdevel | On Thursday, 22 February 2018 at 00:34:59 UTC, kdevel wrote: > Is there a D equivalent of the C++ at method? I would like to reformulate > > repro2.d > --- > void main () > { > import std.stdio; > import std.container; > import std.range; > auto z = Array!char(); > z.reserve(0xC000_0000); > z.capacity.writeln; > z.length.writeln; > for (uint u = 0; u < 0xC000_0000; ++u) > z.insert = 'Y'; > int i = -1073741825; > i.writeln; > z[i] = 'Q'; > z[i].writeln; > } > --- > > $ dmd -O -m32 repro2.d > $ ./repro2 > 3221225472 > 0 > -1073741825 > Q > > such that it fails like the 64 bit version: > > $ dmd -O -m64 repro2.d > $ ./repro2 > > 3221225472 > 0 > -1073741825 > core.exception.RangeError@.../dmd2/linux/bin64/../../src/phobos/std/container/array.d(650): Range violation > ---------------- > ??:? _d_arrayboundsp [0x440d22] > .../dmd2/linux/bin64/../../src/phobos/std/container/array.d:650 inout pure nothrow ref @nogc @safe inout(char) std.container.array.Array!(char).Array.opIndex(ulong) [0x43bb0f] > repro2.d:14 _Dmain [0x43afff] Well in a 32bit program the value 0xBFFF_FFFF(-1073741825) is clearly inside the array. The Array class uses an size_t internaly for storing the length/capacity, that is uint in a 32bit program and ulong in a 64bit program. In the 64bit the value (0xFFFF_FFFF_BFFF_FFFF)(-1073741825) is larger than 0xC000_000 so it will be out of bounds in this case. If you want any negative integer to be out of bounds the capacity cannot be larger than 0x7FFF_FFFF in 32bit programs. But this behavior is strange. Well the really strange/bad part is that it's allowed by the compiler in the first place. I would be very happy if a user was forced to make an explicit cast for int <-> uint conversions. Like we have to do for long -> int conversions. Also signed/unsigned comparisons should be strictly outlawed by the compiler. Eg: uint a = 3; int b = -1; assert(a > b); //No idea what should happen here. |
February 22, 2018 Re: array/Array: "hard" bounds checking | ||||
---|---|---|---|---|
| ||||
Posted in reply to TheFlyingFiddle | On Thursday, 22 February 2018 at 05:22:19 UTC, TheFlyingFiddle wrote:
>
> Eg:
>
> uint a = 3;
> int b = -1;
>
> assert(a > b); //No idea what should happen here.
This is what happens:
assert(cast(int)a > b);
|
February 22, 2018 Re: array/Array: "hard" bounds checking | ||||
---|---|---|---|---|
| ||||
Posted in reply to bauss | On 02/22/2018 10:39 AM, bauss wrote:
> On Thursday, 22 February 2018 at 05:22:19 UTC, TheFlyingFiddle wrote:
>>
>> Eg:
>>
>> uint a = 3;
>> int b = -1;
>>
>> assert(a > b); //No idea what should happen here.
>
> This is what happens:
>
> assert(cast(int)a > b);
Nope. It's `assert(a > cast(uint)b);`.
|
February 22, 2018 Re: array/Array: "hard" bounds checking | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | On Thursday, 22 February 2018 at 12:50:43 UTC, ag0aep6g wrote:
> On 02/22/2018 10:39 AM, bauss wrote:
>> On Thursday, 22 February 2018 at 05:22:19 UTC, TheFlyingFiddle wrote:
>>>
>>> Eg:
>>>
>>> uint a = 3;
>>> int b = -1;
>>>
>>> assert(a > b); //No idea what should happen here.
>>
>> This is what happens:
>>
>> assert(cast(int)a > b);
>
> Nope. It's `assert(a > cast(uint)b);`.
These two posts kind of proved my point :D. And that is why you should never mix signed and unsigned integers. A good thing is that dscanner static analysis will warn you about this stuff (in simple cases at-least).
|
Copyright © 1999-2021 by the D Language Foundation