Reputation: 6295
Since the introduction of C# 7.0's return by reference feature, and based on my understanding that a feature like this would require some rewiring on the compiler to store this reference only on variables located on the heap, is it possible to store a returned reference to a variable on the stack, or does the new ref declaration ensure that the variable is always stored on the heap?
ref int x = ref DoSomething(data);
// Is the value of x now on the stack or the heap? Or is x stored on the stack as a reference and the value on the heap?
My understanding is based on this article:
Finally, the CLR does allow “ref return types”; you could in theory have a method “ref int M() { … }” that returned a reference to an integer variable. If for some bizarre reason we ever decided to allow that in C#, we’d have to fix up the compiler and verifier so that they ensured that it was only possible to return refs to variables that were known to be on the heap, or known to be “lower down” on the stack than the callee.
Upvotes: 2
Views: 399
Reputation: 941635
ref int x
is syntax sugar for int* x
, the way the variable behaves at runtime. Exact same behavior you get when you pass a variable to a method as an argument and the parameter is declared ref
, the caller passes a pointer to the variable. A pointer does not care where the value is stored, and in fact can be stored anywhere. Note that you can't pass a property, it has no storage.
The non-trivial thing they had to do in C# v7 is to make sure you cannot accidentally create a dangling pointer bug. Notorious in languages like C and C++, it is undefined behavior in those languages with no requirement for the compiler to generate a diagnostic. Lots of program with that bug appear to run just fine, until a seemingly trivial change in the program (adding a function call) corrupts the pointed-to value.
Not actually hard to do afaik, local variables of the called method are the trouble makers. They no longer exist after the method returns so the reference becomes invalid. The specific scenario that will give you a compile error in C# v7. But it is fine if the local variable is one of the caller, and it passed in the reference though a parameter, that variable is still alive.
Upvotes: 7
Reputation: 660159
The name of the song is called "Haddocks' Eyes".' 'Oh, that's the name of the song, is it?' Alice said, trying to feel interested. 'No, you don't understand,' the Knight said, looking a little vexed. 'That's what the name is called. The name really is "The Aged Aged Man".' 'Then I ought to have said "That's what the song is called"?' Alice corrected herself. 'No, you oughtn't: that's quite another thing! The song is called "Ways and Means": but that's only what it's called, you know!' 'Well, what is the song, then?' said Alice, who was by this time completely bewildered. 'I was coming to that,' the Knight said. 'The song really is "A-sitting On a Gate": and the tune's my own invention.'
The song, the name of the song, what the name is called, and what the song is called are apparently all different.
There are three things that you must not confuse:
ref int x = ref DoSomething(data);
Is the value of x now on the stack or the heap?
The expression x
is an alias to another variable.
That variable has a value.
Suppose the aliased variable is a value type. Is the aliased variable, and therefore its value, on the temporary pool (aka "stack") or the long-term pool (the "heap")? We don't know. Nor do we care. We know that whichever it is, we are guaranteed that this variable is alive right now.
However we could make a guess: ref returned variables are usually aliases to heap-allocated variables, because we know for sure that they are alive.
Suppose the aliased variable is of reference type. Is the reference stored on the stack or the heap? Again, we do not know, for the same reason. Is the referent of that reference on the stack or the heap? It's either on the heap, or it is null; we are guaranteed of that.
Or is x stored on the stack as a reference and the value on the heap?
By x
do you mean the variable that x
aliases, or do you mean the local x
itself? The local itself is stored in either stack or registers; it is never hoisted to a field of a closure class. The variable aliased could be anywhere, but as noted above, is likely on the heap.
Upvotes: 10