Debug help - Programming in D - extending tail slice terminates sharing unexpectedly. Page 69, 70

Brother Bill brotherbill at mail.com
Mon Oct 20 10:47:09 UTC 2025


On Monday, 20 October 2025 at 10:38:23 UTC, Serg Gini wrote:
> On Monday, 20 October 2025 at 09:50:35 UTC, Brother Bill wrote:
>> So all that guidance of tail appending using 'length' and 
>> 'capacity' is obsolete.
>> That is, if the capacity > length, then one can safely extend 
>> the tail by (capacity - length) elements.
>> The new advice is to just not append to slices either for the 
>> base array or any tail slice array.  Otherwise, breakage or 
>> termination of slice sharing may result.
>>
>> Do I have that correct?
>
> But I'm not sure about slice capacity. it doesn't make any 
> sense for me when it is non-zero
> https://dlang.org/spec/arrays.html#capacity-reserve

I've played with the code and think I understand D's rules for 
sharing or breaking sharing.

1. Extending the base dynamic array up to (capacity – length) 
will continue to maintain sharing with derived slices.
2. Extending the base dynamic array beyond (capacity – length) 
will make a copy of the base dynamic array and break sharing.
3. Extending a derived slice will make a copy of the derived 
slice and break sharing.

source/app.d
```
import std.stdio;

void main()
{
	extendingBaseArraySmallMaintainsSharing();
	extendingBaseArrayLargeDoesNotMaintainSharing();
	extendingSliceDoesNotMaintainSharing();
}

void extendingBaseArraySmallMaintainsSharing()
{
	writeln("=== extendingBaseArraySmallMaintainsSharing ===");
	int[] slice = [1, 3, 5, 7, 9, 11, 13, 15];
	int[] tailSlice = slice[$ / 2 .. $];
	writeln("slice: ", slice, " length: ", slice.length, " capacity: 
", slice.capacity, ", &slice[4]: ", &slice[4]);
	writeln("tailSlice: ", tailSlice, " length: ", tailSlice.length, 
" capacity: ", tailSlice.capacity, " &tailSlice[0]: ", 
&tailSlice[0]);

	slice.length += (slice.capacity - slice.length); // extend to 
capacity
	writeln("slice after: ", slice, " length: ", slice.length, " 
capacity: ", slice.capacity, ", &slice[4]: ", &slice[4]);
	writeln("tailSlice after incrementing length by 1: ", tailSlice, 
" length: ", tailSlice.length, " capacity: ", tailSlice.capacity, 
" &tailSlice[0]: ", &tailSlice[0]);
	tailSlice[0] = 888;
	writeln("After tail slice length increase and changing 
tailSlice[0] to 888. ", " length: ", tailSlice.length, " 
capacity: ", tailSlice.capacity);
	writeln("tailSlice: ", tailSlice);
	writeln("slice    : ", slice);
	writeln;
}

void extendingBaseArrayLargeDoesNotMaintainSharing()
{
	writeln("=== extendingBaseArrayLargeDoesNotMaintainSharing ===");
	int[] slice = [1, 3, 5, 7, 9, 11, 13, 15];
	int[] tailSlice = slice[$ / 2 .. $];
	writeln("slice: ", slice, " length: ", slice.length, " capacity: 
", slice.capacity, ", &slice[4]: ", &slice[4]);
	writeln("tailSlice: ", tailSlice, " length: ", tailSlice.length, 
" capacity: ", tailSlice.capacity, " &tailSlice[0]: ", 
&tailSlice[0]);

	slice.length += (1 + slice.capacity - slice.length); // extend 
just beyond capacity
	writeln("slice after: ", slice, " length: ", slice.length, " 
capacity: ", slice.capacity, ", &slice[4]: ", &slice[4]);
	writeln("tailSlice after incrementing length by 1: ", tailSlice, 
" length: ", tailSlice.length, " capacity: ", tailSlice.capacity, 
" &tailSlice[0]: ", &tailSlice[0]);
	tailSlice[0] = 888;
	writeln("After tail slice length increase and changing 
tailSlice[0] to 888. ", " length: ", tailSlice.length, " 
capacity: ", tailSlice.capacity);
	writeln("tailSlice: ", tailSlice);
	writeln("slice    : ", slice);
	writeln;
}

void extendingSliceDoesNotMaintainSharing()
{
	writeln("=== extendingSliceDoesNotMaintainSharing ===");
	int[] slice = [1, 3, 5, 7, 9, 11, 13, 15];
	int[] tailSlice = slice[$ / 2 .. $];
	writeln("slice: ", slice, " length: ", slice.length, " capacity: 
", slice.capacity, ", &slice[4]: ", &slice[4]);
	writeln("tailSlice: ", tailSlice, " length: ", tailSlice.length, 
" capacity: ", tailSlice.capacity, " &tailSlice[0]: ", 
&tailSlice[0]);

	tailSlice.length += (tailSlice.capacity - tailSlice.length); // 
extend to capacity
	writeln("slice after: ", slice, " length: ", slice.length, " 
capacity: ", slice.capacity, ", &slice[4]: ", &slice[4]);
	writeln("tailSlice after incrementing length by 1: ", tailSlice, 
" length: ", tailSlice.length, " capacity: ", tailSlice.capacity, 
" &tailSlice[0]: ", &tailSlice[0]);
	tailSlice[0] = 888;
	writeln("After tail slice length increase and changing 
tailSlice[0] to 888. ", " length: ", tailSlice.length, " 
capacity: ", tailSlice.capacity);
	writeln("tailSlice: ", tailSlice);
	writeln("slice    : ", slice);
	writeln;
}
```

Console output:
```
=== extendingBaseArraySmallMaintainsSharing ===
slice: [1, 3, 5, 7, 9, 11, 13, 15] length: 8 capacity: 11, 
&slice[4]: 237935F1010
tailSlice: [9, 11, 13, 15] length: 4 capacity: 7 &tailSlice[0]: 
237935F1010
slice after: [1, 3, 5, 7, 9, 11, 13, 15, 0, 0, 0] length: 11 
capacity: 11, &slice[4]: 237935F1010
tailSlice after incrementing length by 1: [9, 11, 13, 15] length: 
4 capacity: 0 &tailSlice[0]: 237935F1010
After tail slice length increase and changing tailSlice[0] to 
888.  length: 4 capacity: 0
tailSlice: [888, 11, 13, 15]
slice    : [1, 3, 5, 7, 888, 11, 13, 15, 0, 0, 0]

=== extendingBaseArrayLargeDoesNotMaintainSharing ===
slice: [1, 3, 5, 7, 9, 11, 13, 15] length: 8 capacity: 11, 
&slice[4]: 237935F1040
tailSlice: [9, 11, 13, 15] length: 4 capacity: 7 &tailSlice[0]: 
237935F1040
slice after: [1, 3, 5, 7, 9, 11, 13, 15, 0, 0, 0, 0] length: 12 
capacity: 15, &slice[4]: 237935F2010
tailSlice after incrementing length by 1: [9, 11, 13, 15] length: 
4 capacity: 7 &tailSlice[0]: 237935F1040
After tail slice length increase and changing tailSlice[0] to 
888.  length: 4 capacity: 7
tailSlice: [888, 11, 13, 15]
slice    : [1, 3, 5, 7, 9, 11, 13, 15, 0, 0, 0, 0]

=== extendingSliceDoesNotMaintainSharing ===
slice: [1, 3, 5, 7, 9, 11, 13, 15] length: 8 capacity: 11, 
&slice[4]: 237935F1070
tailSlice: [9, 11, 13, 15] length: 4 capacity: 7 &tailSlice[0]: 
237935F1070
slice after: [1, 3, 5, 7, 9, 11, 13, 15] length: 8 capacity: 11, 
&slice[4]: 237935F1070
tailSlice after incrementing length by 1: [9, 11, 13, 15, 0, 0, 
0] length: 7 capacity: 7 &tailSlice[0]: 237935F0020
After tail slice length increase and changing tailSlice[0] to 
888.  length: 7 capacity: 7
tailSlice: [888, 11, 13, 15, 0, 0, 0]
slice    : [1, 3, 5, 7, 9, 11, 13, 15]
```


More information about the Digitalmars-d-learn mailing list