core.exception.InvalidMemoryOperationError@(0)

ketmar via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Jan 25 11:15:54 PST 2015


On Sun, 25 Jan 2015 08:41:24 +0000, Bayan Rafeh wrote:

>> I tried what you said and I think I see the problem. I managed to
>> create an example program that duplicates the problem:
>>
>>
>> import std.stdio;
>>
>> class A {
>>     string path;
>>
>>     this(string p) {
>>         path = p;
>>     }
>>     ~this() {
>>     }
>>     void a(){}
>>
>>     void b(){}
>> }
>>
>> class B {
>>     A a;
>>     this() {
>>         this.a = new A("laladiv");
>>     }
>>     ~this() {
>>         delete a;
>>     }
>> }
>>
>> void main() {
>>     B a = new B(); B b = new B(); delete b;
>> }
> 
> The solution was just to remove the "delete a" from the destructor if
> someone comes across this later. Could someone tell me why though?

there is no guarantees on destruction order. and GC will not nullify any 
references to collected data. so, `a` can be already collected and 
finalized when `B.~this()` is called. yet reference is still there, so 
`delete a;` will try to delete already dead object. this will lead to 
crash.

without precise GC collector is not able to automatically nullify all 
"dead" references. and even if there will be such possibility, it can 
slow down collections alot (GC will nullifying alot of references that 
aren't used anyway), so i don't think that it do nullifying.

there is a simple rule: "dtor should not touch GC-managed resources". 
this will not give you "predictable destruction order" (that's why most 
people try to manually delete something in dtor), and this simply will 
not work at all.

if you want predictable destruction order, don't use GC at all, use 
manual memory management. it doesn't matter which hack you will invent to 
force destruction order, any hack will either be very fragile, or will 
not work. this is due to nature of GC-manged memory.

so: don't use GC-managed resources in dtors. don't use in any way -- this 
including accessing 'em. i.e. reading `a.path` in dtor is invalid too. it 
will not necessarily crash, but it's the source of "use after free" error.

and don't even think that you can trick GC using checks from 
`core.memory`! this will not work too. sure, you can check if memory used 
by `a` is still alive, but that memory can be used by completely 
different object!

tl;dr:
1. don't use GC-managed objects in dtors. not even try to access 'em.
2. don't try to trick GC. either don't use it, or cooperate with it.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-learn/attachments/20150125/3d81e2fb/attachment.sig>


More information about the Digitalmars-d-learn mailing list