View mode: basic / threaded / horizontal-split · Log in · Help
September 20, 2011
Dynamic Array Question
Hi!
I'm working on a library written in D.
After some tests I have discovered that my library leaks memory, those leaks are caused by dynamics array that I use in my library.

My question is:
Should dynamics array be deallocated automatically when a procedure returns? There is another way to acomplish this?

Maybe I'm doing something wrong, so, I post the function that causes the leak:

public string getWindowText(HWND hWnd)
{
 int len = GetWindowTextLengthW(hWnd);
 wchar[] t = new wchar[len + 1]; // How to deallocate this?

 GetWindowTextW(hWnd, t.ptr, len);

 /*
  * I'm converting the wchar[] to char[],
  * the variable 't' should be deallocated
  * because I not need it anymore.
  */
 return to!(string)(t[0..len]);
}

Thanks,
Dax
September 20, 2011
Re: Dynamic Array Question
On Tue, 20 Sep 2011 14:06:34 -0400, Dax <dax@mailinator.com> wrote:

> Hi!
> I'm working on a library written in D.
> After some tests I have discovered that my library leaks memory, those  
> leaks are caused by dynamics array that I use in my library.
>
> My question is:
> Should dynamics array be deallocated automatically when a procedure  
> returns?

No, in a GC-enabled language, the GC is responsible for cleaning up the  
memory.

> There is another way to acomplish this?

Yes, you can manually free the memory at your own risk.  Note that in any  
GC-enabled language, more memory is consumed than in a manually-managed  
language.  This is because there is a time period where a memory block is  
unused, but still allocated (i.e. the GC hasn't collected it yet).

D's garbage collector is conservative, which means it may keep some blocks  
in memory even though they are no longer in use.  Also, depending on your  
measurement tools, you may be counting freed memory towards memory usage.   
For example, if a block of memory is deallocated, it's not given back to  
the OS, it simply goes back into a pool to be reallocated again later.

> Maybe I'm doing something wrong, so, I post the function that causes the  
> leak:
>
> public string getWindowText(HWND hWnd)
> {
>   int len = GetWindowTextLengthW(hWnd);
>   wchar[] t = new wchar[len + 1]; // How to deallocate this?
>
>   GetWindowTextW(hWnd, t.ptr, len);
>
>   /*
>    * I'm converting the wchar[] to char[],
>    * the variable 't' should be deallocated
>    * because I not need it anymore.
>    */
>   return to!(string)(t[0..len]);
> }

You can deallocate the original array.  The soon-to-be-deprecated method  
(but easiest) is:

delete t;

To avoid having to change your other code, I'd do this:

wchar[] t = ...;
scope(exit) delete t; // add this line to the end of the function (after  
returning)

There is another way, but it's not as easy:

// put this at the top of file
import core.memory;

...

scope(exit) GC.free(t.ptr);

However, this is what will be required when delete is deprecated.

-Steve
September 20, 2011
Re: Dynamic Array Question
On Tuesday, September 20, 2011 11:06 Dax wrote:
> Hi!
> I'm working on a library written in D.
> After some tests I have discovered that my library leaks memory, those
> leaks are caused by dynamics array that I use in my library.
> 
> My question is:
> Should dynamics array be deallocated automatically when a procedure
> returns? There is another way to acomplish this?
> 
> Maybe I'm doing something wrong, so, I post the function that causes the
> leak:
> 
> public string getWindowText(HWND hWnd)
> {
> int len = GetWindowTextLengthW(hWnd);
> wchar[] t = new wchar[len + 1]; // How to deallocate this?
> 
> GetWindowTextW(hWnd, t.ptr, len);
> 
> /*
> * I'm converting the wchar[] to char[],
> * the variable 't' should be deallocated
> * because I not need it anymore.
> */
> return to!(string)(t[0..len]);
> }

You don't deallocate dynamic arrays. The GC manages them. The GC manages all 
of the memory that you allocate in D with new. If the memory gets freed, it 
gets freed during a garbage collection cycle. When the GC runs is non-
deterministic. I believe that it normally only ever gets called when new is 
called, and it's only going to run when new is called if it thinks that it 
needs to run. The fact that your program doesn't reference a chunk of memory 
anymore is irrelevant until a garbage collection cycle runs. That memory won't 
be freed until then.

However last I heard, the GC still never released memory to the OS, and if 
that's still true, even if the GC collects the memory so that your program can 
reuse it, the memory usage of your program will never actually go down. So, if 
what you're doing is looking at the memory usage of your program, that may 
never go down regardless.

- Jonathan M Davis
September 20, 2011
Re: Dynamic Array Question
On 09/20/2011 08:06 PM, Dax wrote:
> Hi!
> I'm working on a library written in D.
> After some tests I have discovered that my library leaks memory, those leaks are caused by dynamics array that I use in my library.
>

Does it 'leak'? What is your exact setup, why isn't the GC collecting 
that memory?

> My question is:
> Should dynamics array be deallocated automatically when a procedure returns? There is another way to acomplish this?
>
> Maybe I'm doing something wrong, so, I post the function that causes the leak:
>
> public string getWindowText(HWND hWnd)
> {
>    int len = GetWindowTextLengthW(hWnd);
>    wchar[] t = new wchar[len + 1]; // How to deallocate this?
>
>    GetWindowTextW(hWnd, t.ptr, len);
>
>    /*
>     * I'm converting the wchar[] to char[],
>     * the variable 't' should be deallocated
>     * because I not need it anymore.
>     */
>    return to!(string)(t[0..len]);
> }
>

Unless the string gets extremely long, you could allocate it on the stack:

wchar[] t=(cast(wchar*)alloca(wchar.sizeof*(len+1)))[0..len+1];
September 20, 2011
Re: Dynamic Array Question
>
> Does it 'leak'? What is your exact setup, why isn't the GC collecting
> that memory?
>

I have a Label class with a text() property that calls the procedure 
that I have written in my first post and returns the result.


I have posted here because I was looking the memory usage (more 
precisely the process' private working set) with Process Explorer (from 
Sysinternals) and I saw the private working set increase and increase 
every time text() property il called, so I trought it was a memory leak.

But, if the Garbage Collector handles the memory allocation of dynamic 
arrays, the problem is solved.


Thanks to all for help me with this problem! :)
September 20, 2011
Re: Dynamic Array Question
> To avoid having to change your other code, I'd do this:
> 
> wchar[] t = ...;
> scope(exit) delete t; // add this line to the end of the function (after  
> returning)
> 
> There is another way, but it's not as easy:
> 
> // put this at the top of file
> import core.memory;
> 
> ...
> 
> scope(exit) GC.free(t.ptr);

does "scope wchar[] t = ...;" work too ?
September 21, 2011
Re: Dynamic Array Question
On Tuesday, September 20, 2011 21:48:10 Christophe wrote:
> > To avoid having to change your other code, I'd do this:
> > 
> > wchar[] t = ...;
> > scope(exit) delete t; // add this line to the end of the function (after
> > returning)
> > 
> > There is another way, but it's not as easy:
> > 
> > // put this at the top of file
> > import core.memory;
> > 
> > ...
> > 
> > scope(exit) GC.free(t.ptr);
> 
> does "scope wchar[] t = ...;" work too ?

I'm not sure, but scope as a modifier on local variables like that is going to 
be removed from the language. std.typecons.Scoped is replacing it.

However, unless you're having major memory issues, I really wouldn't worry 
about it. Just let the garbage collector do its thing. It's not the best, but 
it works fine in most cases.

- Jonathan M Davis
September 21, 2011
Re: Dynamic Array Question
On Tue, 20 Sep 2011 14:28:54 -0400, Steven Schveighoffer wrote:

> You can deallocate the original array.  The soon-to-be-deprecated method
> (but easiest) is:
> 
> delete t;
> 
> To avoid having to change your other code, I'd do this:
> 
> wchar[] t = ...;
> scope(exit) delete t; // add this line to the end of the function (after
> returning)

Unless I missed something, delete is being removed from the language.
September 22, 2011
Re: Dynamic Array Question
On Wed, 21 Sep 2011 00:09:08 -0400, Jesse Phillips  
<jessekphillips+d@gmail.com> wrote:

> On Tue, 20 Sep 2011 14:28:54 -0400, Steven Schveighoffer wrote:
>
>> You can deallocate the original array.  The soon-to-be-deprecated method

Note:                                      ^^^^^^^^^^^^^^^^^^^^^^^^^

:)

>> (but easiest) is:
>>
>> delete t;
>>
>> To avoid having to change your other code, I'd do this:
>>
>> wchar[] t = ...;
>> scope(exit) delete t; // add this line to the end of the function (after
>> returning)
>
> Unless I missed something, delete is being removed from the language.

-Steve
Top | Discussion index | About this forum | D home