On 4/1/22 12:24 PM, Ali Çehreli wrote:
>void main() {
auto a = new int[1_000_000];
auto b = a[0..1]; // Hold on to the first element
a = a[$-1..$]; // Drop all but the last element
// Are the middle elements gone, or is b keeping
// them alive just because it still holds the very
// first pointer?
// Attempt to access original elements through
// a pointer to the first element. Bug?
auto c = b.ptr[0..1_000_000];
Not a bug, the array still exists and is allocated (the pointer is keeping it alive). Remember, the GC manages the memory, not the slice.
e.g. if this were an array of structs with destructors, those destructors would not be called just because they aren't referenced by some slice.
>}
One assumption might be that the GC remembers the single large allocation as one and all of the elements are still available? But if it considers slices and their lengths specially, then it would see that the mid section is not referenced any more.
It's not a consideration for the GC, but possibly the compiler. The GC has no visibility into slices that hold references to its memory block. It only has knowledge of pointers to its memory block (and then only indirectly via scanning).
Only the compiler could consider this distinction. As of yet, I don't think D has stated one way or another whether this could be exploited.
But thinking about how a non-native array type might be implemented, I don't think there's any possible way D could consider a reference to one element to not be a reference to all elements.
>A related question is whether the memory for earlier elements are freed as they are popped off from the front. I know by experience that the memory for earlier elements are indeed freed. So one can use D's arrays as queues without memory issues: Add to the end, pop from the front...
No, because removing the reference does not mean there are no other references.
-Steve