Thread overview
-release compiler switch and associative arrays
Oct 09, 2011
Graham Cole
Oct 11, 2011
Vijay Nayar
Oct 11, 2011
Vijay Nayar
Oct 12, 2011
Kagamin
Oct 11, 2011
Don
October 09, 2011
I understand from the documentation that the "-release" compiler switch turns off "array bounds checking for system and trusted functions".

Is it correct that the following code should seg fault when compiled with "-release" ?

string[string] h;
h["abc"] = "def";
string s = h["aaa"];

I.e. retrieving from an associative array for a non existent key.

I would have thought that an exception should be generated in this case when compiled with "-release" (as it is when compiled without).

This code behaves the same when compiled by both D1 and D2.

Should I report this as a bug ?

October 09, 2011
On 09-10-2011 13:24, Graham Cole wrote:
> I understand from the documentation that the "-release" compiler switch turns off "array bounds checking for system and trusted functions".
>
> Is it correct that the following code should seg fault when compiled with "-release" ?
>
> string[string] h;
> h["abc"] = "def";
> string s = h["aaa"];
>
> I.e. retrieving from an associative array for a non existent key.
>
> I would have thought that an exception should be generated in this case when compiled with
> "-release" (as it is when compiled without).
>
> This code behaves the same when compiled by both D1 and D2.
>
> Should I report this as a bug ?
>

To generate a sensible exception in the first place, you'd have to actually *do* bounds checking. When you disable bounds checking, you're just allowing it to read/write beyond the bounds of the array, which any sane OS won't be too happy with. :)

- Alex
October 11, 2011
On Sun, 09 Oct 2011 12:24:24 +0100, Graham Cole wrote:

> I understand from the documentation that the "-release" compiler switch turns off "array bounds checking for system and trusted functions".
> 
> Is it correct that the following code should seg fault when compiled with "-release" ?
> 
> string[string] h;
> h["abc"] = "def";
> string s = h["aaa"];
> 
> I.e. retrieving from an associative array for a non existent key.
> 
> I would have thought that an exception should be generated in this case when compiled with "-release" (as it is when compiled without).
> 
> This code behaves the same when compiled by both D1 and D2.
> 
> Should I report this as a bug ?

Howdy Mr. Cole,

The "-release" flag disables runtime checks of data ranges and bounds of things like arrays and pointers.  These checks take a little bit of time, but they help you catch an error as early as possible.

Without the "-release" flag, the checks are removed, so there are two
possibilities when you index an array index.
  A.  The memory address is out of bounds for the program as a whole, and
results in a segfault.
  B.  The memory address is in range for the the program as a whole, but
has no been initialized or refers to data in a completely different
variable.

Errors of the second type are especially sinister and very hard to debug.  Consider the following program:

void main() {
    int[] ages = [28, 23, 40];
    assert(ages[0] == 28);
    ages[3] = 54;
    assert(ages[3] == 54);
}

$ dmd -release bounds.d
$ ./bounds
# No segfault because the address is within the address space
# for the program allowed by the OS.

$ dmd bounds.d
$ ./bounds
core.exception.RangeError@bounds(6): Range violation
----------------
./bounds(onRangeError+0x28) [0x805f908]
./bounds(_d_array_bounds+0x16) [0x805d516]
./bounds() [0x805ae8e]
./bounds(_Dmain+0x6c) [0x805ae40]
./bounds(_D2rt6dmain24mainUiPPaZi7runMainMFZv+0x1a) [0x805d96e]
./bounds(_D2rt6dmain24mainUiPPaZi7tryExecMFMDFZvZv+0x20) [0x805d608]
./bounds(_D2rt6dmain24mainUiPPaZi6runAllMFZv+0x32) [0x805d9b2]
./bounds(_D2rt6dmain24mainUiPPaZi7tryExecMFMDFZvZv+0x20) [0x805d608]
./bounds(main+0x94) [0x805d5b4]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xe7) [0xb7681e37]
./bounds() [0x805ad21]
----------------

 - Vijay




October 11, 2011
On Tue, 11 Oct 2011 14:45:38 +0000, Vijay Nayar wrote:

> On Sun, 09 Oct 2011 12:24:24 +0100, Graham Cole wrote:
> 
>> I understand from the documentation that the "-release" compiler switch turns off "array bounds checking for system and trusted functions".
>> 
>> Is it correct that the following code should seg fault when compiled with "-release" ?
>> 
>> string[string] h;
>> h["abc"] = "def";
>> string s = h["aaa"];
>> 
>> I.e. retrieving from an associative array for a non existent key.
>> 
>> I would have thought that an exception should be generated in this case when compiled with "-release" (as it is when compiled without).
>> 
>> This code behaves the same when compiled by both D1 and D2.
>> 
>> Should I report this as a bug ?

Oh, if your question is specifically about associative arrays, like string [string], then the reason why there is no out-of-bounds problem is that D associative arrays are sparsely populated and support insertion.

http://www.digitalmars.com/d/2.0/arrays.html#associative

 - Vijay
October 11, 2011
On 09.10.2011 13:24, Graham Cole wrote:
> I understand from the documentation that the "-release" compiler switch turns off "array bounds checking for system and trusted functions".
>
> Is it correct that the following code should seg fault when compiled with "-release" ?
>
> string[string] h;
> h["abc"] = "def";
> string s = h["aaa"];
>
> I.e. retrieving from an associative array for a non existent key.
>
> I would have thought that an exception should be generated in this case when compiled with
> "-release" (as it is when compiled without).
>
> This code behaves the same when compiled by both D1 and D2.
>
> Should I report this as a bug ?

In the compiler source (e2ir.c, IndexExp::toElem), AA checking is generated only when bounds checking is enabled. So it's intentional.

What really happens is that h[xxx] returns a pointer to the element, or null if none.
If it's null, then a bounds error is thrown. But this check is removed for -release.
Then string s= h["aaa"] dereferences the null pointer, and you get a segfault.

Here's a funny side-effect: the code below works fine with -release. p is null. But you get an array bounds error if not using -release.

 string[string] h;
 h["abc"] = "def";
 string *p = &h["aaa"];

October 12, 2011
Vijay Nayar Wrote:

> void main() {
>     int[] ages = [28, 23, 40];
>     assert(ages[0] == 28);
>     ages[3] = 54;
>     assert(ages[3] == 54);
> }
> 
> $ dmd -release bounds.d
> $ ./bounds
> # No segfault because the address is within the address space
> # for the program allowed by the OS.

Walter said this feature was removed and now you need -no-bounds-check switch to turn checks off in release mode.