www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - want to confirm: gc will not free a non-gc-allocated field of a

reply mw <mingwu gmail.com> writes:
Hi,

Suppose I have this code:

```
class GCAllocated {
   float[] data;

   this() {
     // non-gc-allocated field
     this.data = cast(float[])(core.stdc.stdlib.malloc(nBytes)[0 
.. nBytes]);
   }
}

void foo() {
   auto obj = new GCAllocated();  // gc-allocated owning object
   ...
}

```

So when `obj` is cleanup by the GC, obj.data won't be freed by 
the GC: because the `data` is non-gc-allocated (and it's 
allocated on the non-gc heap), the GC scanner will just skip that 
field during a collection scan. Is this understanding correct?

I need this behavior for a special purpose, so I want to confirm 
it.

Thanks.
Jun 06 2022
next sibling parent reply max haughton <maxhaton gmail.com> writes:
On Monday, 6 June 2022 at 22:18:08 UTC, mw wrote:
 Hi,

 Suppose I have this code:

 ```
 class GCAllocated {
   float[] data;

   this() {
     // non-gc-allocated field
     this.data = cast(float[])(core.stdc.stdlib.malloc(nBytes)[0 
 .. nBytes]);
   }
 }

 void foo() {
   auto obj = new GCAllocated();  // gc-allocated owning object
   ...
 }

 ```

 So when `obj` is cleanup by the GC, obj.data won't be freed by 
 the GC: because the `data` is non-gc-allocated (and it's 
 allocated on the non-gc heap), the GC scanner will just skip 
 that field during a collection scan. Is this understanding 
 correct?

 I need this behavior for a special purpose, so I want to 
 confirm it.

 Thanks.
float[] doesn't contain pointers, so the GC won't do anything to or with it.
Jun 06 2022
next sibling parent mw <mingwu gmail.com> writes:
On Monday, 6 June 2022 at 22:22:05 UTC, max haughton wrote:
 float[] doesn't contain pointers, so the GC won't do anything 
 to or with it.
does every array have a .ptr attr? https://dlang.org/spec/arrays.html Dynamic Array Properties .ptr Returns a pointer to the first element of the array.
Jun 06 2022
prev sibling parent reply ag0aep6g <anonymous example.com> writes:
On 07.06.22 00:22, max haughton wrote:
 float[] doesn't contain pointers, so the GC won't do anything to or with 
 it.
wat float[] is a pointer (plus a length). The GC will deal with it like any other pointer.
Jun 06 2022
parent reply max haughton <maxhaton gmail.com> writes:
On Tuesday, 7 June 2022 at 00:40:56 UTC, ag0aep6g wrote:
 On 07.06.22 00:22, max haughton wrote:
 float[] doesn't contain pointers, so the GC won't do anything 
 to or with it.
wat float[] is a pointer (plus a length). The GC will deal with it like any other pointer.
I'm talking about the data in the array. void[] might contain pointers, float[] does not so it won't be scanned. Or at least shouldn't be... This is why you shouldn't use void[] for everything if you can help it. ``` void main() { import std.stdio; auto voidArray = typeid(void[]); auto floatArray = typeid(float[]); writeln(voidArray.next.flags() & 1 ); writeln(floatArray.next.flags() & 1); } ```
Jun 06 2022
parent reply ag0aep6g <anonymous example.com> writes:
On 07.06.22 03:02, max haughton wrote:
 I'm talking about the data in the array.
 
 void[] might contain pointers, float[] does not so it won't be scanned.
That wasn't mw's question.
Jun 07 2022
parent reply max haughton <maxhaton gmail.com> writes:
On Tuesday, 7 June 2022 at 08:56:29 UTC, ag0aep6g wrote:
 On 07.06.22 03:02, max haughton wrote:
 I'm talking about the data in the array.
 
 void[] might contain pointers, float[] does not so it won't be 
 scanned.
That wasn't mw's question.
I also answered this in my original one IIRC. There's nothing too free because the GC didn't allocate it. Every allocator needs to either have a GC or a fast way to free memory which includes checking whether it owns memory in the first place. annoyingly you can't express this in the malloc/free pattern very well at all. One of the many gifts C has given the world.
Jun 07 2022
parent reply ag0aep6g <anonymous example.com> writes:
On 07.06.22 11:00, max haughton wrote:
 On Tuesday, 7 June 2022 at 08:56:29 UTC, ag0aep6g wrote:
[...]
 That wasn't mw's question.
I also answered this in my original one IIRC.
You didn't.
Jun 07 2022
parent max haughton <maxhaton gmail.com> writes:
On Tuesday, 7 June 2022 at 09:12:25 UTC, ag0aep6g wrote:
 On 07.06.22 11:00, max haughton wrote:
 On Tuesday, 7 June 2022 at 08:56:29 UTC, ag0aep6g wrote:
[...]
 That wasn't mw's question.
I also answered this in my original one IIRC.
You didn't.
Ok I must have assumed it was obvious it wouldn't free it.
Jun 07 2022
prev sibling next sibling parent reply Guillaume Piolat <first.last gmail.com> writes:
On Monday, 6 June 2022 at 22:18:08 UTC, mw wrote:
 So when `obj` is cleanup by the GC, obj.data won't be freed by 
 the GC: because the `data` is non-gc-allocated (and it's 
 allocated on the non-gc heap), the GC scanner will just skip 
 that field during a collection scan. Is this understanding 
 correct?
My understanding is that while scanning, the GC will see the data.ptr pointer, but will not scan the area it points to since it's not in a GC range (the runtime can distinguish managed pointer and other pointers). After scanning, when obj is non-reachable, the GC will destroy it but that won't lead to a reclaim of data.ptr since it knows it doesn't own that.
Jun 06 2022
parent Guillaume Piolat <first.last gmail.com> writes:
On Monday, 6 June 2022 at 22:24:45 UTC, Guillaume Piolat wrote:
 My understanding is that while scanning, the GC will see the 
 data.ptr pointer, but will not scan the area it points to since 
 it's not in a GC range (the runtime can distinguish managed 
 pointer and other pointers).

 After scanning, when obj is non-reachable, the GC will destroy 
 it but that won't lead to a reclaim of data.ptr since it knows 
 it doesn't own that.
In D, the ownership of slice is purely determined by the memory area it points to. If it points into GC memory then it's a GC slice.
Jun 06 2022
prev sibling next sibling parent "H. S. Teoh" <hsteoh qfbox.info> writes:
On Mon, Jun 06, 2022 at 10:18:08PM +0000, mw via Digitalmars-d-learn wrote:
 Hi,
 
 Suppose I have this code:
 
 ```
 class GCAllocated {
   float[] data;
 
   this() {
     // non-gc-allocated field
     this.data = cast(float[])(core.stdc.stdlib.malloc(nBytes)[0 .. nBytes]);
   }
 }
 
 void foo() {
   auto obj = new GCAllocated();  // gc-allocated owning object
   ...
 }
 
 ```
 
 So when `obj` is cleanup by the GC, obj.data won't be freed by the GC:
 because the `data` is non-gc-allocated (and it's allocated on the
 non-gc heap), the GC scanner will just skip that field during a
 collection scan. Is this understanding correct?
 
 I need this behavior for a special purpose, so I want to confirm it.
[...] Short answer: yes, the GC will not do anything with that field. Long answer: even if the GC wanted to do something about that field, how could it? It has no information about how it was allocated. As far as the GC is concerned, it's just a pointer + size pair, just like any other array, and the pointer happens to point outside of GC-allocated memory. Beyond that, the GC knows nothing else about the pointer. Is it allocated by malloc? Is it pointing to static memory? Is it some user-defined custom allocator? Is it some random garbage value? Who knows. The GC knows nothing about the pointer, so it conservatively ignores it. On a more general implementational note, D's GC is conservative, meaning that if an aligned pointer-sized value looks like it might be a pointer value, the GC will assume, erring on the side of being overly cautious, that it *is* a pointer value, and mark any GC memory that it might happen to point to as live. The value could be an int or long, and the GC wouldn't know any better. (More recent precise implementations may skip some of these false positives, though.) The same principle applies, though: if the pointer has a value that the GC doesn't know about (i.e., doesn't point to any of the known GC blocks) then the GC will conservatively just ignore it. T -- Give a man a fish, and he eats once. Teach a man to fish, and he will sit forever.
Jun 06 2022
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/6/22 6:18 PM, mw wrote:
 Hi,
 
 Suppose I have this code:
 
 ```
 class GCAllocated {
    float[] data;
 
    this() {
      // non-gc-allocated field
      this.data = cast(float[])(core.stdc.stdlib.malloc(nBytes)[0 .. 
 nBytes]);
    }
 }
 
 void foo() {
    auto obj = new GCAllocated();  // gc-allocated owning object
    ...
 }
 
 ```
 
 So when `obj` is cleanup by the GC, obj.data won't be freed by the GC: 
 because the `data` is non-gc-allocated (and it's allocated on the non-gc 
 heap), the GC scanner will just skip that field during a collection 
 scan. Is this understanding correct?
Others have given answers on this, but I just want to clarify -- the GC does *not* use any type information to scan for pointers. The default GC has one bit to tell it whether a block contains pointers or not (if true, it will treat every word as if it were a pointer), and it does not understand array references, just pointers. The precise GC has a bitmap of which words in the block are pointers, and it also does not understand array references. So you are safe, it will see the pointer inside the array reference, and see that it doesn't point at GC memory, so nothing further will be done. -Steve
Jun 07 2022
parent mw <mingwu gmail.com> writes:
On Tuesday, 7 June 2022 at 13:56:23 UTC, Steven Schveighoffer 
wrote:
 So you are safe, it will see the pointer inside the array 
 reference, and see that it doesn't point at GC memory, so 
 nothing further will be done.
Thanks for the detailed explanation, and everyone who has replied.
Jun 07 2022