Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spec is incorrect regarding interfacing C with GC and local variables #4117

Open
dlangBugzillaToGithub opened this issue Sep 22, 2021 · 2 comments

Comments

@dlangBugzillaToGithub
Copy link

Steven Schveighoffer (@schveiguy) reported this on 2021-09-22T19:44:01Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=22331

Description

For reference:

https://forum.dlang.org/post/xchnfzvpmxgytqprbosz@forum.dlang.org
https://forum.dlang.org/post/siajpj$3p2$1@digitalmars.com

When a local variable is kept in a temporary register, the GC will not see it after that register is used for something else. This means the object can be collected.

This becomes a problem when you store the pointer outside the GC's view. The spec currently lists the following as a remedy for such a thing:

> Leaving a pointer to it on the stack (as a parameter or automatic variable), as the garbage collector will scan the stack.

Typically, one leaves it on the stack by declaring an automatic variable, and assigning it to that pointer. However, if the compiler notices that the variable isn't used later on, it will not actually put even local variables on the stack. This results in the object sometimes being collected seemingly when the local variable is still in scope and should be referencing the block.

The spec should be changed to remove this possible remedy, or the remedy should be clarified to outline how exactly to ensure that a variable gets put on the stack.

Advanced optimizers are working against this goal by trying to avoid writing registers to memory if it can avoid doing so. This may require changes to the compiler and/or library to provide a good way to ensure the stack is storing the data. If none of that is possible, the remedy should be removed.

Other languages that rely on a GC have a mechanism that does this exact operation:

C#: `GC.KeepAlive`: https://docs.microsoft.com/en-us/dotnet/api/system.gc.keepalive?view=net-5.0
Go: `runtime.KeepAlive`: https://pkg.go.dev/runtime#KeepAlive

In both those examples, the function itself does nothing, it is just an intrinsic to the compiler to note that the lifetime of the object should last until at least that line.
@dlangBugzillaToGithub
Copy link
Author

dfj1esp02 commented on 2021-09-22T20:57:11Z

Umm, the stack advice is solid, you just apparently conflate lifetime with lexical scope.

@dlangBugzillaToGithub
Copy link
Author

schveiguy (@schveiguy) commented on 2021-09-22T21:56:59Z

(In reply to anonymous4 from comment #1)
> Umm, the stack advice is solid, you just apparently conflate lifetime with
> lexical scope.

How would you leave a pointer on the stack?

This doesn't work:

------
void foo()
{
  auto c = new Class; // not on the stack
  c.method(); // c still not stored on the stack.
  GC.collect(); // possibly will collect c.
}
------

The recommendation in the spec is to use a "parameter or automatic variable". This doesn't work. If the recommendation is to store on the stack is solid, it should provide a solid mechanism to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant