Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
June 24, 2012 aa.remove in a destructor | ||||
---|---|---|---|---|
| ||||
this code: class X{ string[string] s; this() { s["s"] = "S"; } ~this() { s.remove("s"); } } void main() { X x = new X(); } produces this: core.exception.InvalidMemoryOperationError because the aa is calling gc_free during a collection, apparently. Should I be expecting the above code to run without error or not? thanks |
June 24, 2012 Re: aa.remove in a destructor | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ellery Newcomer | I've been having the same problem as well, but I never figured out the link to the remove() call in the destructor. The only solution I've found is to use GC.removeRoot() on the table, but it's an untested and potentially dangerous solution. |
June 24, 2012 Re: aa.remove in a destructor | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ellery Newcomer | On 24-Jun-12 08:15, Ellery Newcomer wrote: > this code: > > class X{ > string[string] s; > this() { > s["s"] = "S"; > } > ~this() { > s.remove("s"); > > } > } > > void main() { > X x = new X(); > } > > produces this: > > core.exception.InvalidMemoryOperationError > > because the aa is calling gc_free during a collection, apparently. > > Should I be expecting the above code to run without error or not? > > thanks I think no, as any with operation involving GC. For instance while you are removing elements table may decide to rehash itself and that means it may trigger allocation. -- Dmitry Olshansky |
June 24, 2012 Re: aa.remove in a destructor | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dmitry Olshansky | On Sunday, June 24, 2012 11:53:37 Dmitry Olshansky wrote:
> On 24-Jun-12 08:15, Ellery Newcomer wrote:
> > this code:
> >
> > class X{
> >
> > string[string] s;
> > this() {
> >
> > s["s"] = "S";
> >
> > }
> > ~this() {
> >
> > s.remove("s");
> >
> > }
> >
> > }
> >
> > void main() {
> >
> > X x = new X();
> >
> > }
> >
> > produces this:
> >
> > core.exception.InvalidMemoryOperationError
> >
> > because the aa is calling gc_free during a collection, apparently.
> >
> > Should I be expecting the above code to run without error or not?
> >
> > thanks
>
> I think no, as any with operation involving GC. For instance while you are removing elements table may decide to rehash itself and that means it may trigger allocation.
Basically, you should never do anything in a class' destructor/finalizer which could ever trigger the GC in any way. If that's going to be a problem, then you need to do whatever you're doing differently. Really, class destructor/finalizers are for managing resources which _aren't_ memory-related or involve memory which is not from the GC heap.
- Jonathan M Davis
|
June 24, 2012 Re: aa.remove in a destructor | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dmitry Olshansky | On 06/24/2012 02:53 AM, Dmitry Olshansky wrote:
>
> I think no, as any with operation involving GC. For instance while you
> are removing elements table may decide to rehash itself and that means
> it may trigger allocation.
>
okay, it looks like my [inherited] code is using aa's to map D objects to C wrapper objects and keep references to the D objects around. If the builtin aa's aren't going to work, I'll need something else.
Come to think of it, though, shouldn't the standard library provide an aa implementation that doesn't rely on the gc?
|
June 26, 2012 Re: aa.remove in a destructor | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ellery Newcomer | On 06/24/2012 01:56 PM, Ellery Newcomer wrote:
>
> Come to think of it, though, shouldn't the standard library provide an
> aa implementation that doesn't rely on the gc?
ah, screw it, I'll just write my own.
|
June 26, 2012 Re: aa.remove in a destructor | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ellery Newcomer | On Sun, 24 Jun 2012 14:56:20 -0400, Ellery Newcomer <ellery-newcomer@utulsa.edu> wrote:
> On 06/24/2012 02:53 AM, Dmitry Olshansky wrote:
>>
>> I think no, as any with operation involving GC. For instance while you
>> are removing elements table may decide to rehash itself and that means
>> it may trigger allocation.
>>
>
> okay, it looks like my [inherited] code is using aa's to map D objects to C wrapper objects and keep references to the D objects around. If the builtin aa's aren't going to work, I'll need something else.
>
> Come to think of it, though, shouldn't the standard library provide an aa implementation that doesn't rely on the gc?
I want to red flag this code for another reason.
You must *never* access GC-allocated references in a destructor, to do so will make the program crash randomly.
The destructor is only for releasing non-GC resources, nothing else. You can't even *read* them reliably.
The reason being, the AA you have referenced may have *already been collected* by the time your dtor is called.
If you do manage to make an AA that is not GC allocated, you should be fine. You should be able to do this with dcollections, if you write a C malloc-based allocator (note to self, I should have this implemented...).
-Steve
|
June 28, 2012 Re: aa.remove in a destructor | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 06/26/2012 12:41 PM, Steven Schveighoffer wrote: > > I want to red flag this code for another reason. > > You must *never* access GC-allocated references in a destructor, to do > so will make the program crash randomly. The docs should be so assertive (not that I read them or anything). > > The destructor is only for releasing non-GC resources, nothing else. You > can't even *read* them reliably. > > The reason being, the AA you have referenced may have *already been > collected* by the time your dtor is called. > > If you do manage to make an AA that is not GC allocated, you should be > fine. You should be able to do this with dcollections, if you write a C > malloc-based allocator (note to self, I should have this implemented...). > > -Steve Yeah, I had a thought a while ago that std.container.RedBlackTree would work for me because I remember there being an allocate function in it somewhere when I was abusing it into shape for multi_index, but then the allocate function was private, and the class was final, and I don't think there was a deallocate function in the std.container version. I started to fork it but then changed my mind and built allocators into multi_index instead. It works great now, and probably doesn't leak too much. Didn't look at dcollections, though. |
Copyright © 1999-2021 by the D Language Foundation