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.

Reply via email to