www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DMD optimization bug?

reply Jacob Carlborg <doob me.com> writes:
The code below works fine without optimizations. But with optimizations 
(the -O flag) turned on it segfaults. The behavior with optimizations 
turned on is a bit different depending on which version of DMD I try and 
if I compile for 32 or 64bit.

DMD 2.062 64bit: Segfault
DMD 2.062 32bit: Prints a huge array then segfault
DMD 2.061 64bit: Segfault
DMD 2.061 32bit: Prints a fairly small array (10 elements) with random 
numbers
DMD head (7dcc72a997) 32bit: Bus error: 10

I'm using Mac OS X 10.8.2.

import std.stdio;

int[]* getDeserializedSlice ()
{
     void[] a = [1, 2, 3, 4, 5].dup;
     auto b = &a;

     if (auto c = b)
         auto d = &(cast(int[]) *c)[1 .. 1 + 2];

     return null;
}

void main ()
{
     writeln(*getDeserializedSlice());
}

Is the above code supposed to work? The test case might look a bit 
strange, the full source code is here:

https://github.com/jacob-carlborg/orange/blob/master/orange/serialization/Serializer.d#L1672

-- 
/Jacob Carlborg
Mar 21 2013
next sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 21 March 2013 20:29, Jacob Carlborg <doob me.com> wrote:

 The code below works fine without optimizations. But with optimizations
 (the -O flag) turned on it segfaults. The behavior with optimizations
 turned on is a bit different depending on which version of DMD I try and if
 I compile for 32 or 64bit.

 DMD 2.062 64bit: Segfault
 DMD 2.062 32bit: Prints a huge array then segfault
 DMD 2.061 64bit: Segfault
 DMD 2.061 32bit: Prints a fairly small array (10 elements) with random
 numbers
 DMD head (7dcc72a997) 32bit: Bus error: 10

 I'm using Mac OS X 10.8.2.

 import std.stdio;

 int[]* getDeserializedSlice ()
 {
     void[] a = [1, 2, 3, 4, 5].dup;
     auto b = &a;

     if (auto c = b)
         auto d = &(cast(int[]) *c)[1 .. 1 + 2];

     return null;
 }

 void main ()
 {
     writeln(*getDeserializedSlice(**));
 }

 Is the above code supposed to work? The test case might look a bit
 strange, the full source code is here:

 https://github.com/jacob-**carlborg/orange/blob/master/**
 orange/serialization/**Serializer.d#L1672<https://github.com/jacob-carlborg/orange/blob/master/orange/serialization/Serializer.d#L1672>

 --
 /Jacob Carlborg
As I see it, that code should *always* cause a segmentation fault. You are returning 'null', and then dereferencing it... Regards -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Mar 21 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-03-21 22:46, Iain Buclaw wrote:
 On 21 March 2013 20:29, Jacob Carlborg <doob me.com
 <mailto:doob me.com>> wrote:

     The code below works fine without optimizations. But with
     optimizations (the -O flag) turned on it segfaults. The behavior
     with optimizations turned on is a bit different depending on which
     version of DMD I try and if I compile for 32 or 64bit.

     DMD 2.062 64bit: Segfault
     DMD 2.062 32bit: Prints a huge array then segfault
     DMD 2.061 64bit: Segfault
     DMD 2.061 32bit: Prints a fairly small array (10 elements) with
     random numbers
     DMD head (7dcc72a997) 32bit: Bus error: 10

     I'm using Mac OS X 10.8.2.

     import std.stdio;

     int[]* getDeserializedSlice ()
     {
          void[] a = [1, 2, 3, 4, 5].dup;
          auto b = &a;

          if (auto c = b)
              auto d = &(cast(int[]) *c)[1 .. 1 + 2];

          return null;
     }

     void main ()
     {
          writeln(*getDeserializedSlice(__));
     }

     Is the above code supposed to work? The test case might look a bit
     strange, the full source code is here:

     https://github.com/jacob-__carlborg/orange/blob/master/__orange/serialization/__Serializer.d#L1672
     <https://github.com/jacob-carlborg/orange/blob/master/orange/serialization/Serializer.d#L1672>

     --
     /Jacob Carlborg
Crap, that example was incorrect, it should look like this: return &(cast(int[]) *c)[1 .. 1 + 2]; -- /Jacob Carlborg
Mar 22 2013
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
22-Mar-2013 11:26, Jacob Carlborg пишет:
 On 2013-03-21 22:46, Iain Buclaw wrote:
 On 21 March 2013 20:29, Jacob Carlborg <doob me.com
 <mailto:doob me.com>> wrote:

     The code below works fine without optimizations. But with
     optimizations (the -O flag) turned on it segfaults. The behavior
     with optimizations turned on is a bit different depending on which
     version of DMD I try and if I compile for 32 or 64bit.

     DMD 2.062 64bit: Segfault
     DMD 2.062 32bit: Prints a huge array then segfault
     DMD 2.061 64bit: Segfault
     DMD 2.061 32bit: Prints a fairly small array (10 elements) with
     random numbers
     DMD head (7dcc72a997) 32bit: Bus error: 10

     I'm using Mac OS X 10.8.2.

     import std.stdio;

     int[]* getDeserializedSlice ()
     {
          void[] a = [1, 2, 3, 4, 5].dup;
          auto b = &a;

          if (auto c = b)
              auto d = &(cast(int[]) *c)[1 .. 1 + 2];

          return null;
     }

     void main ()
     {
          writeln(*getDeserializedSlice(__));
     }

     Is the above code supposed to work? The test case might look a bit
     strange, the full source code is here:


 https://github.com/jacob-__carlborg/orange/blob/master/__orange/serialization/__Serializer.d#L1672


 <https://github.com/jacob-carlborg/orange/blob/master/orange/serialization/Serializer.d#L1672>


     --
     /Jacob Carlborg
Crap, that example was incorrect, it should look like this: return &(cast(int[]) *c)[1 .. 1 + 2];
OK so c points to [1, 2, 3, 4, 5] (and who knows if it's 5 bytes or 5 ints) slice. *c is that slice, (cast(int[])*c)[1..3] is pieces of that slice an r-value. Mmm so you are returning a pointer to r-value (a local temporary)? What's the point of the code? -- Dmitry Olshansky
Mar 22 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-03-22 09:14, Dmitry Olshansky wrote:

 OK so c points to [1, 2, 3, 4, 5] (and who knows if it's 5 bytes or 5
 ints) slice. *c is that slice, (cast(int[])*c)[1..3] is pieces of that
 slice an r-value.
 Mmm so you are returning a pointer to r-value (a local temporary)?
 What's the point of the code?
I'm showing here a reduced minimal test case, that's why it looks strange. The full source code is here: https://github.com/jacob-carlborg/orange/blob/master/orange/serialization/Serializer.d#L1672 private T* getDeserializedSlice (T) (Slice slice) { if (auto array = slice.id in deserializedSlices) return &(cast(T) *array)[slice.offset .. slice.offset + slice.length]; return null; } In my serializer I'm storing already deserialized arrays in a associative array, looking like this: void[][size_t] deserializedSlices; The "size_t" is a unique identification. What I'm doing here is returning a slice from an already deserialized array. "Slice" is a struct as follows: struct Slice { size_t id; // id of the array the slice originates to size_t offset; // start position of the slice in the array size_t length; // length of the slice } What I'm doing in "getDeserializedSlice" is checking if the slice id is available in the associative array. If it is I deference the array (since I'm getting a pointer from the "in" expression), then casting it to the correct array type. After that I'm slicing the array and returns a pointer to it. I figured that was safe since it's always stored in the associative array, but that might not be the case. I guess I could return the slice by an out parameter instead and return a bool from the function. -- /Jacob Carlborg
Mar 22 2013
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
22-Mar-2013 13:01, Jacob Carlborg пишет:
 On 2013-03-22 09:14, Dmitry Olshansky wrote:

 OK so c points to [1, 2, 3, 4, 5] (and who knows if it's 5 bytes or 5
 ints) slice. *c is that slice, (cast(int[])*c)[1..3] is pieces of that
 slice an r-value.
 Mmm so you are returning a pointer to r-value (a local temporary)?
 What's the point of the code?
I'm showing here a reduced minimal test case, that's why it looks strange. The full source code is here:
It doesn't change the fact that pointer to slice is not going to work. Esp pointer to stack-allocated slice. You'll get garbage and sometimes segfaults. What's wrong with returning slice by value ?
 https://github.com/jacob-carlborg/orange/blob/master/orange/serialization/Serializer.d#L1672
Exactly what you describe there is not going to work at all. Taking address of temporary slice (a[x..y] is a temporary value) is welcoming a segfault. -- Dmitry Olshansky
Mar 22 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-03-22 10:07, Dmitry Olshansky wrote:

 What's wrong with returning slice by value ?
I want to know both if it exists and get back the value. I could use an out parameter for that though. -- /Jacob Carlborg
Mar 22 2013
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
22-Mar-2013 15:56, Jacob Carlborg пишет:
 On 2013-03-22 10:07, Dmitry Olshansky wrote:

 What's wrong with returning slice by value ?
I want to know both if it exists and get back the value. I could use an out parameter for that though.
Yes, that or ref parameter. Another option is: return null - doesn't exists (both ptr and .length are zeros) return a slice that has zero length and non-zero ptr - exists but empty Dunno if it's suitable to what your doing with it later on. -- Dmitry Olshansky
Mar 22 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-03-22 13:00, Dmitry Olshansky wrote:

 Yes, that or ref parameter.

 Another option is:

 return null - doesn't exists (both ptr and .length are zeros)

 return a slice that has zero length and non-zero ptr - exists but empty

 Dunno if it's suitable to what your doing with it later on.
Yeah, that would probably also work. Thanks for the help. BTW, was it only luck that it worked with out optimizations? -- /Jacob Carlborg
Mar 22 2013
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
22-Mar-2013 16:25, Jacob Carlborg пишет:
 On 2013-03-22 13:00, Dmitry Olshansky wrote:

 Yes, that or ref parameter.

 Another option is:

 return null - doesn't exists (both ptr and .length are zeros)

 return a slice that has zero length and non-zero ptr - exists but empty

 Dunno if it's suitable to what your doing with it later on.
Yeah, that would probably also work. Thanks for the help. BTW, was it only luck that it worked with out optimizations?
Pure and hellish kind of luck. Well there is a lot of folklore that prescribes that luck is more of demonic then celestial nature :) -- Dmitry Olshansky
Mar 22 2013
parent Jacob Carlborg <doob me.com> writes:
On 2013-03-22 13:28, Dmitry Olshansky wrote:

 Pure and hellish kind of luck.

 Well there is a lot of  folklore that prescribes that luck is more of
 demonic then celestial nature :)
Hehe :) -- /Jacob Carlborg
Mar 22 2013
prev sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 21 March 2013 21:46, Iain Buclaw <ibuclaw ubuntu.com> wrote:

 On 21 March 2013 20:29, Jacob Carlborg <doob me.com> wrote:

 The code below works fine without optimizations. But with optimizations
 (the -O flag) turned on it segfaults. The behavior with optimizations
 turned on is a bit different depending on which version of DMD I try and if
 I compile for 32 or 64bit.

 DMD 2.062 64bit: Segfault
 DMD 2.062 32bit: Prints a huge array then segfault
 DMD 2.061 64bit: Segfault
 DMD 2.061 32bit: Prints a fairly small array (10 elements) with random
 numbers
 DMD head (7dcc72a997) 32bit: Bus error: 10

 I'm using Mac OS X 10.8.2.

 import std.stdio;

 int[]* getDeserializedSlice ()
 {
     void[] a = [1, 2, 3, 4, 5].dup;
     auto b = &a;

     if (auto c = b)
         auto d = &(cast(int[]) *c)[1 .. 1 + 2];

     return null;
 }

 void main ()
 {
     writeln(*getDeserializedSlice());
 }

 Is the above code supposed to work? The test case might look a bit
 strange, the full source code is here:


 https://github.com/jacob-carlborg/orange/blob/master/orange/serialization/Serializer.d#L1672

 --
 /Jacob Carlborg
As I see it, that code should *always* cause a segmentation fault. You are returning 'null', and then dereferencing it...
Just to be clear, the program should stop at the point of: writeln(*getDeserializedSlice()) Where getSerializedSlice() has returned 'null' and then null gets dereferenced. All other behaviours where the program tries to print *(null) are wrong code. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Mar 21 2013