Jump to page: 1 2
Thread overview
want to confirm: gc will not free a non-gc-allocated field of a gc-allocated object?
Jun 06, 2022
mw
Jun 06, 2022
max haughton
Jun 06, 2022
mw
Jun 07, 2022
ag0aep6g
Jun 07, 2022
max haughton
Jun 07, 2022
ag0aep6g
Jun 07, 2022
max haughton
Jun 07, 2022
ag0aep6g
Jun 07, 2022
max haughton
Jun 06, 2022
Guillaume Piolat
Jun 06, 2022
Guillaume Piolat
Jun 06, 2022
H. S. Teoh
Jun 07, 2022
mw
June 06, 2022

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.

June 06, 2022

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.

June 06, 2022

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.

June 06, 2022

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.

June 06, 2022

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.

June 06, 2022
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.
June 07, 2022
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.
June 07, 2022
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);
}
```
June 07, 2022
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.
June 07, 2022
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.
« First   ‹ Prev
1 2