4

How can I prove that boxing cause storing a variable in heap instead of stack?

boxing

I want some code to show my students that boxing cause storing a variable in heap instead of stack.

Boxing and Unboxing

trincot
  • 317,000
  • 35
  • 244
  • 286
Mohamad Shiralizadeh
  • 8,329
  • 6
  • 58
  • 93
  • 3
    Is it even possible to show this conclusively within managed code? The exact memory management strategies are supposed to be "invisible" to application code. Maybe you have to step outside of the "code sandbox" and look at things like memory dumps of the runtime system? – Thilo Feb 05 '17 at 11:37
  • 1
    What's wrong with the image you already have? I'd think any code that would prove it's in the heap would be more difficult for the student to understand than the general principal. – juharr Feb 05 '17 at 11:39
  • 3
    Use the debugger, Debug > Windows > Memory > Memory 1. Put `O` in the Address box. Shows the address where the object is stored, compare to the address of another object variable, say `object O2 = new object();`. They are very close together, that proves it. Similarly, put `&j` in the Address box. Compare to the value of the EBP and ESP registers as displayed by Debug > Windows > Registers. Almost the same, proves that the unboxed variable is stored on the stack. – Hans Passant Feb 05 '17 at 11:49
  • 4
    Standard remark: "Stack and Heap are implementation details". And the very fact that it is not so easy to demonstrate (in managed code) should make you wonder how much time you want to spend on this. – H H Feb 05 '17 at 11:53
  • 1
    Take care: while a boxed value goes on the heap, but it is *not* true that a value type always goes on the stack. It's a mistake to think of boxing as a process that somehow moves things from the stack to the heap. All it does is make a value object available as a reference object. The fact that it does so by creating something on the heap is almost uninteresting. – Jeroen Mostert Feb 06 '17 at 10:04

1 Answers1

0

It is surprisingly hard to distinguish between heap and stack objects (which is intentional, because .NET wants to hide this implementation detail from programmers).

One approach you could take is to compare address-based default hash codes of boxed objects, and observe that they keep changing (demo):

static object MakeBoxed() {
    int n = 5;
    object a = n;
    return a;
}
public static void Main() {
    for (int i = 0 ; i != 10 ; i++) {
        object a = MakeBoxed();
        Console.WriteLine(RuntimeHelpers.GetHashCode(a));
    }
}

Objects created inside MakeBoxed cannot be on the stack, because the stack frame of MakeBoxed is deactivated after the call. Further, they cannot be in the stack frame of Main, because stack frames do not grow, yet all objects have different addresses (default hash codes).

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    You observe the same behavior when changing `MakeBoxed` to simply returning an `int` without boxing. Worse, you get the same behaviour simply by writing `var a = 5;` with no method call at all. I feel like it's impossible to tell the difference simply because the heap and the stack are implementation details. – Rob Feb 06 '17 at 03:56
  • 1
    @Rob If you return an `int`, the boxing will happen anyway when calling `RuntimeHelpers.GetHashCode(object)`. Writing `object a = 5` performs boxing, too, so it's not surprising that you get the same behavior. – Sergey Kalinichenko Feb 06 '17 at 04:06
  • @dasblinkenlight Why `RuntimeHelpers.GetHashCode()` returns different value for an object each time? – Mohamad Shiralizadeh Feb 06 '17 at 05:18
  • @Mohamadshiralizadeh If you pass the same object, you will get the same number. If numbers are different, then the objects are different (although the same number could be returned for different objects). – Sergey Kalinichenko Feb 06 '17 at 09:08
  • @dasblinkenlight yes, I was wrong. I should think about your answer more.. – Mohamad Shiralizadeh Feb 06 '17 at 09:44