GC doesn't collect where expected
Steven Schveighoffer
schveiguy at gmail.com
Mon Jun 19 16:43:30 UTC 2023
On 6/19/23 12:13 PM, axricard wrote:
> I'm doing some experiments with ldc2 GC, by instrumenting it and
> printing basic information (what is allocated and freed)
>
> My first tests are made on this sample :
>
> ```
>>> cat test2.d
> import core.memory;
>
> class Bar { int bar; }
>
> class Foo {
>
> this()
> {
> this.bar = new Bar;
> }
>
> Bar bar;
> }
>
>
> void func()
> {
> Foo f2 = new Foo;
> }
>
> int main()
> {
> Foo f = new Foo;
>
> func();
> GC.collect();
>
> return 0;
> }
>
> ```
>
> When trying to run the instrumented druntime, I get a strange behavior :
> the first collection (done with GC.collect) doesn't sweep anything (in
> particular, it doesn't sweep memory allocated in _func()_). The whole
> sweeping is done when program finish, at cleanup. I don't understand why
> : memory allocated in _func()_ shouldn't be accessible from any root at
> first collection, right ?
>
> ```
> ╰─> /instrumented-ldc2 -g -O0 test2.d --disable-gc2stack
> --disable-d-passes --of test2 && ./test2 "--DRT-gcopt=cleanup:collect
> fork:0 parallel:0 verbose:2"
>
>
> [test2.d:26] new 'test2.Foo' (24 bytes) => p = 0x7f3a0454d000
> [test2.d:10] new 'test2.Bar' (20 bytes) => p = 0x7f3a0454d020
> [test2.d:21] new 'test2.Foo' (24 bytes) => p = 0x7f3a0454d040
> [test2.d:10] new 'test2.Bar' (20 bytes) => p = 0x7f3a0454d060
>
> ============ COLLECTION =============
> ============= MARKING ==============
> marking range: [0x7fff22337a60..0x7fff22339000] (0x15a0)
> range: [0x7f3a0454d000..0x7f3a0454d020] (0x20)
> range: [0x7f3a0454d040..0x7f3a0454d060] (0x20)
> marking range: [0x7f3a0464d720..0x7f3a0464d8b9] (0x199)
> marking range: [0x46c610..0x47b3b8] (0xeda8)
> ============= SWEEPING ==============
> =====================================================
>
>
> ============ COLLECTION =============
> ============= MARKING ==============
> marking range: [0x46c610..0x47b3b8] (0xeda8)
> ============= SWEEPING ==============
> Freeing test2.Foo (test2.d:26; 24 bytes) (0x7f3a0454d000). AGE
> : 1/2
> Freeing test2.Bar (test2.d:10; 20 bytes) (0x7f3a0454d020). AGE
> : 1/2
> Freeing test2.Foo (test2.d:21; 24 bytes) (0x7f3a0454d040). AGE
> : 1/2
> Freeing test2.Bar (test2.d:10; 20 bytes) (0x7f3a0454d060). AGE
> : 1/2
> =====================================================
> ```
>
In general, the language does not guarantee when the GC will collect
your item.
In this specific case, most likely it's a stale register or stack
reference. One way I usually use to ensure such things is to call a
function that destroys the existing stack:
```d
void clobber()
{
int[2048] x;
}
```
Calling this function will clear out 2048x4 bytes of data to 0 on the stack.
-Steve
More information about the Digitalmars-d-learn
mailing list