GC.calloc(), then what?

safety0ff via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri Jun 27 01:49:07 PDT 2014


On Friday, 27 June 2014 at 08:17:07 UTC, Ali Çehreli wrote:
> Thank you for your responses. I am partly enlightened. :p

I know you're a knowledgeable person in the D community, I may 
have stated many things you already knew, but I tried to answer 
the questions as-is.


> On 06/27/2014 12:34 AM, safety0ff wrote:
>
> > Add range is usually for cases when you use
> stdc.stdlib.malloc/calloc
> > and place pointers to GC managed memory within that memory.
> This allows
> > the GC to scan that memory for pointers during collection,
> otherwise it
> > may reclaim memory which is pointed to my malloc'd memory.
>
> One part that I don't understand in the documentation is "if p 
> points into a GC-managed memory block, addRange does not mark 
> this block as live".
>
> [SNIP]
>
> See, that's confusing: What does that mean? I still hold the 
> memory block anyway; what does the GC achieve by scanning my 
> memory if it's not going to follow references anyway?

The GC _will_ follow references (i.e. scan deeply,) that's the 
whole point of addRange.
What that documentation is saying is that:

If you pass a range R through addRange, and R lies in the GC 
heap, then once there are no pointers (roots) to R, the GC will 
collect it anyway regardless that you called addRange on it.

In other words, prefer using addRoot for GC memory and addRange 
for non-GC memory.


> >> 4) Are the random bit patterns in a malloc()'ed memory
> always a
> >> concern for false pointers? Does that become a concern after
> calling
> >> addRoot() or addRange()?
> >
> > If by malloc you're talking about stdc.stdlib.malloc then:
> > It only becomes a concern after you call addRange,
>
> But addRange doesn't seem to make sense for stdlib.malloc'ed 
> memory, right? The reason is, that memory is not managed by the 
> GC so there is no danger of losing that memory due to a 
> collection anyway. It will go away only when I call stdlib.free.

addRange almost exclusively makes sense with stdlib.malloc'ed 
memory.
As you've stated: If you pass it GC memory it does not mark the 
block as live.

I believe the answer above clears things up: the GC does scan the 
range, and scanning is always "deep" (i.e. when it finds pointers 
to unmarked GC memory, it marks them.)

Conversely, addRoot exclusively makes sense with GC memory.

> > If you're talking about GC.malloc():
> > Currently the GC zeros the memory unless you allocate NO_SCAN
> memory, so
> > it only differs in the NO_SCAN case.
>
> So, the GC's default behavior is to scan the memory, 
> necessitating clearing the contents? That seems to make 
> GC.malloc() behave the same as GC.calloc() by default, doesn't 
> it?


I don't believe it's necessary to clear it, it's just a measure 
against false pointers (AFAIK.)


> So, is this guideline right?
>
>   "GC.malloc() makes sense only with NO_SCAN."


I wouldn't make a guideline like that, just say that: if you want 
the memory to be guaranteed to be zero'd use GC.calloc.

However, due to GC internals (for preventing false pointers,) 
GC.malloc'd memory  will often be zero'd anyway.

> >> If so, why would anyone ever malloc() instead of always
> calloc()'ing?
> >
> > To save on redundant zero'ing.
>
> And again, redundant zero'ing is saved only when used with 
> NO_SCAN.

Yup.

> I think I finally understand the main difference between 
> stdlib.malloc and GC.malloc: The latter gets collected by the 
> GC.

Yup.

> Another question: Do GC.malloc'ed and GC.calloc'ed memory 
> scanned deep?

Yes, only NO_SCAN memory doesn't get scanned, everything else 
does.



More information about the Digitalmars-d-learn mailing list