is it a bug or what?

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Thu Jan 22 06:19:12 PST 2015


On 1/22/15 8:44 AM, collerblade wrote:
> Dear D user, i have this code:
>
> import core.sys.windows.windows;
>
> real[] a;
> while(1) {
>    a.length=4096*4096;
>    a=null;
>
>    Sleep(2000);
> }
>
> It allocates memory, but its never gets freed, just keep going up, and
> after 10 secs, memoryexception is thrown. I checked the pointer it is GC
> safe (attributes is 10). Am i missing something?

Are you compiling 64-bit code or 32-bit? It makes a huge difference.

A real is going to be 16-byte aligned. This means real[4096*4096] is 
allocating 1/4GB per allocation. This consumes 1/16th of your total 
address space on 32-bit address space.

The GC in D is conservative. This means that on 32-bit architecture, any 
4-byte segment scanned by the GC (whether it's a pointer or not) that 
happens to point into the array you allocated is going to keep that 
memory pinned. Because any 4-byte garbage has a 1:16 chance of pointing 
there, odds are good that this will happen. Then it keeps happening, you 
eventually run out of memory.

Now, some possible explanation of why GC.malloc might work while this 
does not:

GC.malloc allocates exactly 4096*4096*16 bytes. Setting a.length goes 
through the append code. Because extending length is considered an 
appending event, it *over-allocates* by a certain factor, expecting you 
to keep appending. (this is how appending can be amortized O(1) 
performance). This means the amount of memory allocated is larger than 
1/4GB. Therefore the chance of failing by setting a.length is going to 
be higher than with using GC.malloc directly, but it could fail with 
either case.

Answers?

1. Manually free such a large array when done with it.
2. Do not allocate such large arrays.
3. Use 64-bit code generation (-m64 on DMD windows, even if you are on 
Win64) if possible.

-Steve


More information about the Digitalmars-d mailing list