Arrays of noncopyables/Invalid memory operation

H. S. Teoh via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Feb 18 17:30:13 PST 2016


On Thu, Feb 18, 2016 at 05:18:33PM -0800, Ali Çehreli via Digitalmars-d-learn wrote:
> On 02/18/2016 12:12 PM, Ali Çehreli wrote:
> 
> >  > Hmm, why does the destructor of object 60 run in the middle of
> >  > nowhere?
> >
> > It so happens that the GC decides to collect when moving the array
> > to a new location at that point. If you add the following to the
> > beginning of main, you will see that the next object to destroy is
> > 59, then 58, etc.
> >
> >      import core.memory;
> >      GC.disable;
> >
> > So, everything makes sense other than throwing in a destructor
> > having issues with the current GC. :-/
> 
> No, it doesn't make sense to me anymore.
> 
> All we're doing here is growing an array. There shouldn't be any
> destructor calls when just doing that, no? As the array grows, the
> elements should be "moved" to the new location; why the destructor? I
> hope this is related to the recent fix.
[...]

Consider this:

	struct HasDtor {
		int data;
		~this() { ... }
	}
	HasDtor[] func(HasDtor[] arr) {
		HasDtor[] middleSlice;
		for (i; 0 .. 1000) {
			arr ~= HasDtor(i);
			if (i == 500) {
				middleSlice = arr;
			}
		}
		return arr;
	}

Suppose the array gets moved sometime after i=500 because it ran out of
space in the current memory location.  Since there is another slice
middleSlice pointing at the old data, it's not just a matter of *moving*
the elements over to the new location; they have to be *copied* over so
that there are now two copies of the original elements -- the GC doesn't
know whether func may try to access the original elements through
middleSlice, so it cannot just move them. Only when middleSlice goes out
of scope, can the old elements be destructed.

So we see that when an array is grown, the elements cannot simply be
moved to the new location; we must make copies of them, otherwise any
slice of the old data will become invalid. So after an array is moved,
there will be two copies of data, and if the original elements are
unreferenced after all, the GC will call the dtors when it runs the next
collection cycle.  Then when the new elements become unreferenced, the
dtors will be called again at the following collection cycle, on the new
copies of the elements.


T

-- 
It always amuses me that Windows has a Safe Mode during bootup. Does that mean that Windows is normally unsafe?


More information about the Digitalmars-d-learn mailing list