www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Explicitly Freeing Memory

reply "Maxime Chevalier-Boisvert" <maximechevalierb gmail.com> writes:
I posted a thread the other day explaining that I was running 
into a memory leak issue which is very hard to debug. There seems 
to be a false pointer somewhere, and I have no way of knowing 
where that is or which object is being pointed to. I decided to 
take the easy way out and explicitly free memory when I don't 
need it. Unfortunately, this brings about more problems.

I'm trying to explicitly free chunks of memory allocated with 
GC.malloc() in a destructor. This works fine while the program is 
running, but when the program terminates, it seems the GC calls 
all destructors in an arbitrary order. I then get a 
core.exception.InvalidMemoryOperationError because I'm trying to 
free memory that is already freed.

Not quite sure where to go from here... I guess I'd have to 
allocate all of the objects I want to free outside of GC'd space, 
but D doesn't seem to provide a convenient syntax for doing so. 
The alternate solution I'm considering is to have a special 
function to destroy all the objects owned by my parent object 
before destroying the parent object itself, and calling this 
function explicitly.
Nov 18 2014
next sibling parent reply "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Wed, Nov 19, 2014 at 03:47:03AM +0000, Maxime Chevalier-Boisvert via
Digitalmars-d-learn wrote:
[...]
 I'm trying to explicitly free chunks of memory allocated with
 GC.malloc() in a destructor. This works fine while the program is
 running, but when the program terminates, it seems the GC calls all
 destructors in an arbitrary order. I then get a
 core.exception.InvalidMemoryOperationError because I'm trying to free
 memory that is already freed.
[...] Yeah, it is well-known that relying on destructor calling order is a bad idea. The GC makes no guarantees about what order destructors will get called, if they get called at all. Also, calling GC allocation / deallocation functions from inside a dtor is also a bad idea, since the GC is not reentrant. Unfortunately I don't have any good suggestions... I have been avoiding depending on dtors in D because of the aforementioned issues (and more), so I haven't had much experience in debugging dtor-related problems in D. T -- An elephant: A mouse built to government specifications. -- Robert Heinlein
Nov 18 2014
parent "Maxime Chevalier-Boisvert" <maximechevalierb gmail.com> writes:
 Unfortunately I don't have any good suggestions... I have been 
 avoiding
 depending on dtors in D because of the aforementioned issues 
 (and more),
 so I haven't had much experience in debugging dtor-related 
 problems in
 D.
I decided to just free everything explicitly: https://github.com/maximecb/Higgs/blob/03931178deb5794bf27b1020542d102a08286c07/source/runtime/vm.d#L784 It seems to address my memory leak issue for the moment: `make test` uses about 1/3 the memory and runs more than twice as fast.
Nov 19 2014
prev sibling next sibling parent "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Wednesday, 19 November 2014 at 03:47:04 UTC, Maxime 
Chevalier-Boisvert wrote:
 I posted a thread the other day explaining that I was running 
 into a memory leak issue which is very hard to debug. There 
 seems to be a false pointer somewhere, and I have no way of 
 knowing where that is or which object is being pointed to. I 
 decided to take the easy way out and explicitly free memory 
 when I don't need it. Unfortunately, this brings about more 
 problems.

 I'm trying to explicitly free chunks of memory allocated with 
 GC.malloc() in a destructor. This works fine while the program 
 is running, but when the program terminates, it seems the GC 
 calls all destructors in an arbitrary order. I then get a 
 core.exception.InvalidMemoryOperationError because I'm trying 
 to free memory that is already freed.
InvalidMemoryOperationError occurs when you're trying to invoke GC functions during a GC pass (because the current D GC is non-reentrant). This can occur if you explicitly free objects from the destructor, and the destructor is invoked by the GC. I suppose you can work around this by using a separate function which deallocates owned objects' memory. P.S. Still working on Diamond.
Nov 18 2014
prev sibling parent "Kagamin" <spam here.lot> writes:
You can control it by creating a global flag and checking it 
before freeing.
Nov 19 2014