Jump to page: 1 2
Thread overview
Array slice length confusion
Jul 08, 2009
Tim Matthews
Jul 08, 2009
Kagamin
Jul 08, 2009
Kagamin
Jul 08, 2009
Tim Matthews
Jul 09, 2009
Tim Matthews
Jul 09, 2009
Tim Matthews
Jul 09, 2009
Kagamin
Jul 09, 2009
Tim Matthews
Jul 09, 2009
Daniel Keep
Jul 09, 2009
grauzone
Jul 09, 2009
BCS
Jul 09, 2009
Tim Matthews
Jul 09, 2009
BCS
Jul 09, 2009
Tim Matthews
Jul 09, 2009
BCS
July 08, 2009
First off if this has been asked so many times please just ignore this. You should be able to collapse this whole subject in most good new readers plus it is in d.learn out of the way so I expect no "ahh here we go again" sort of replies.

Anyway I like how you can get a slice of array that is just a view into the original. If I modify the slice, it modifies the full original array which can be very useful. If however I modify the length of the slice which I was doing in an attempt to extend the view, it becomes it's own array.

This example should help explain what I mean:

module test;

import std.stdio;

void main()
{
    char[5] a = "Hello";
    char[] b;
    b = a[1..3]; //b is a view into a
    writeln(a); //(Hello)
    writeln(b); //(el)
    b[0] = 'a'; //no copy on write
    writeln(a); //(Hallo)
    writeln(b); //(al)
    b.length = b.length+2; //COW on length change?
    b[0] = 'z'; //does not modify a
    writeln(a); //(Hallo)
    writeln(b); //(zl)
}


Was this a design choice, bug, undefined behavior, etc...?
July 08, 2009
Tim Matthews Wrote:

> Was this a design choice, bug, undefined behavior, etc...?

Design choice. In order to widen slice to should recreate it from the original array.
July 08, 2009
Kagamin Wrote:

> Tim Matthews Wrote:
> 
> > Was this a design choice, bug, undefined behavior, etc...?
> 
> Design choice. In order to widen slice to should recreate it from the original array.

For this I use begin markers:

ubyte[] buff=new ubyte[100];
int half=buff.length/2;
ubyte[] buff1=buff[0..half];
ubyte[] buff2=buff[half..$];
July 08, 2009
Kagamin wrote:
> For this I use begin markers:
> 
> ubyte[] buff=new ubyte[100];
> int half=buff.length/2;
> ubyte[] buff1=buff[0..half];
> ubyte[] buff2=buff[half..$];

I actually think this has nothing to do with my OP.
July 08, 2009
On Wed, 08 Jul 2009 02:48:31 -0400, Tim Matthews <tim.matthews7@gmail.com> wrote:

> Was this a design choice, bug, undefined behavior, etc...?

design choice.

A slice *is* an array in the current design.  Increasing the length may or may not make a copy of it.  An array slice doesn't know it was originally part of another array (i.e. there are no references back to the original array) so how would it know that there is data around it?  The only exception is appending to a prefix slice.  If a slice starts at the front of an allocated array, the runtime cannot tell that it was not the original array, so it clobbers data that was in the original array:

char[] str = "blah".dup;
char[] sl = str[0..1];
sl ~= "r";
assert(str == "brah");

BTW, all of this is defined behavior, see http://www.digitalmars.com/d/2.0/arrays.html#resize

-Steve
July 09, 2009
Steven Schveighoffer wrote:
> On Wed, 08 Jul 2009 02:48:31 -0400, Tim Matthews <tim.matthews7@gmail.com> wrote:
> 
>> Was this a design choice, bug, undefined behavior, etc...?
> 
> design choice.
> 
> A slice *is* an array in the current design.  Increasing the length may or may not make a copy of it.  An array slice doesn't know it was originally part of another array (i.e. there are no references back to the original array) so how would it know that there is data around it?  The only exception is appending to a prefix slice.  If a slice starts at the front of an allocated array, the runtime cannot tell that it was not the original array, so it clobbers data that was in the original array:
> 
> char[] str = "blah".dup;
> char[] sl = str[0..1];
> sl ~= "r";
> assert(str == "brah");
> 
> BTW, all of this is defined behavior, see http://www.digitalmars.com/d/2.0/arrays.html#resize
> 
> -Steve

I thought a slice would behave slighty different due to some sort of meta data that is a separate area of memory so it doesn't effect D's abi.

Anyway if anyone gets here through a search engine the correct code assuming you can guarantee it is a slice and that doesn't go out of bounds. It is a systems language after all :)

module test;

import std.stdio;

void resizeView(T)(ref T[] slice, size_t newLength)
{
    (cast(size_t*)(&slice))[0] = newLength;
}

void main()
{
    char[5] a = "hello";
    char[] b = a[1..3];
    writeln(a); //(hello)
    writeln(b); //(el)
    resizeView(b, b.length+1);
    writeln(a); //(hello)
    writeln(b); //(ell)
}


July 09, 2009
On Wed, 08 Jul 2009 23:09:52 -0400, Tim Matthews <tim.matthews7@gmail.com> wrote:

> Steven Schveighoffer wrote:
>> On Wed, 08 Jul 2009 02:48:31 -0400, Tim Matthews <tim.matthews7@gmail.com> wrote:
>>
>>> Was this a design choice, bug, undefined behavior, etc...?
>>  design choice.
>>  A slice *is* an array in the current design.  Increasing the length may or may not make a copy of it.  An array slice doesn't know it was originally part of another array (i.e. there are no references back to the original array) so how would it know that there is data around it?  The only exception is appending to a prefix slice.  If a slice starts at the front of an allocated array, the runtime cannot tell that it was not the original array, so it clobbers data that was in the original array:
>>  char[] str = "blah".dup;
>> char[] sl = str[0..1];
>> sl ~= "r";
>> assert(str == "brah");
>>  BTW, all of this is defined behavior, see http://www.digitalmars.com/d/2.0/arrays.html#resize
>>  -Steve
>
> I thought a slice would behave slighty different due to some sort of meta data that is a separate area of memory so it doesn't effect D's abi.
>
> Anyway if anyone gets here through a search engine the correct code assuming you can guarantee it is a slice and that doesn't go out of bounds. It is a systems language after all :)
>
> module test;
>
> import std.stdio;
>
> void resizeView(T)(ref T[] slice, size_t newLength)
> {
>      (cast(size_t*)(&slice))[0] = newLength;
> }
>
> void main()
> {
>      char[5] a = "hello";
>      char[] b = a[1..3];
>      writeln(a); //(hello)
>      writeln(b); //(el)
>      resizeView(b, b.length+1);
>      writeln(a); //(hello)
>      writeln(b); //(ell)
> }

This is really not a good idea.  You've removed one of the core features of the array -- memory safety.  Doing this is just asking for memory corruption.  You should either re-slice the original array, or create a type that has a reference to the original array so it can be resliced:

start with:

struct TimSlice(T)
{
  T[] slice;
  alias slice this;
  T[] srcArray;

  // override length property
  size_t length() {return slice.length;}
  void length(size_t) {/* use srcArray here to re-slice */}
}

This is assuming you are using D2, of course.  With D1, it's more difficult.

-Steve
July 09, 2009
Steven Schveighoffer wrote:
> This is really not a good idea.  You've removed one of the core features of the array -- memory safety.  Doing this is just asking for memory corruption.  You should either re-slice the original array, or create a type that has a reference to the original array so it can be resliced

I explicitly said that it was unsafe code and off course most situations would be better suited with the extra abstraction or re slice the original.
July 09, 2009
Hello Tim,

> Anyway I like how you can get a slice of array that is just a view
> into the original. If I modify the slice, it modifies the full
> original array which can be very useful. If however I modify the
> length of the slice which I was doing in an attempt to extend the
> view, it becomes it's own array.
> 
[...]
>
> Was this a design choice, bug, undefined behavior, etc...?
> 

you can grab a larger chunk like this


char[] buff1 = something;
char[] buff2 = buff1[10..20];

buff2 = buff2.ptr[0..20];

note this is unsafe and will give you no warnings if you extend past the end of buff1;


July 09, 2009
BCS wrote:
> Hello Tim,
> 
>> Anyway I like how you can get a slice of array that is just a view
>> into the original. If I modify the slice, it modifies the full
>> original array which can be very useful. If however I modify the
>> length of the slice which I was doing in an attempt to extend the
>> view, it becomes it's own array.
>>
> [...]
>>
>> Was this a design choice, bug, undefined behavior, etc...?
>>
> 
> you can grab a larger chunk like this
> 
> 
> char[] buff1 = something;
> char[] buff2 = buff1[10..20];
> 
> buff2 = buff2.ptr[0..20];
> 
> note this is unsafe and will give you no warnings if you extend past the end of buff1;
> 
> 

I know that but I when I said I was trying to extend the view I really mean that I was just trying to extend the view. Also depending on what news reader you use you should see that it branched off in a particular direction to a solution.
« First   ‹ Prev
1 2