4

I am new to programming and this is creating a lot of confusion for me.

Suppose we have the following statement:

Int32 i = 1;

i's content is stored on memory, which will be four bytes : 00000000 00000000 00000000 00000001

How does CLR access this memory location later? Does CLR store the address to this memory block somewhere?

user657697
  • 43
  • 4
  • It is generally bad practice to use the non-aliased types in c#. Int32 should just be "int" Int64 is "long" – Mranz Oct 30 '11 at 17:11
  • 3
    @Mranz Considering that his question is more about the `clr` than `C#`, it's probably better to use .NET names instead of C# aliases. – xanatos Oct 30 '11 at 17:20
  • @xanatos It is tagged c# – Mranz Oct 30 '11 at 17:34
  • 1
    @Mranz And he is using the C# syntax. And that I know :-) In the end you did the right thing telling him that he souldn't normally use `Int32`, but this was the 1 in 1000 cases where it was ok to use it (because, in the end, the C# specifications don't tell anything about memory) – xanatos Oct 30 '11 at 17:44
  • 1
    @Mranz: There are a number of reasons to use the type names instead of the alias keywords, for example whenever you want to emphasize the size of the type, which is common for serialization code for networking and/or interop, in order to yield a specific layout. – Ben Voigt Oct 30 '11 at 18:31
  • @BenVoigt I can see value in doing that in c++ where the size of something like long isn't defined in the standard, but it is in C#. int is 4 bytes, 32 bits, and should be common knowledge. – Mranz Oct 31 '11 at 17:48

4 Answers4

4

System.Int32 is a value type, no references used.

In fact, a local variable may never be in memory at all, if the compiler can find a CPU register to hold it during its entire life.

If it is in memory, its address will be found by adding an offset to the stack pointer (ESP) or to the address of the reference-typed (class in C#) object that contains it.

In the code generated from the JIT, variables of value types are indistinguishable from variables used by native code (there's no object header or anything like that).

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
3

The compiler keeps track of where the variable is, so that it can create code that will access it in the right way.

In this case you are declaring a local variable, so it will be allocated on the stack.

The program will not access the variable at a specific address, but as an offset from the base pointer, which points to the stack frame of the current method.

The code to set the variable to 1 can for example look like this when it's compiled into machine code for a 32 bit application:

mov dword ptr [ebp-8],1

The ebp register points to the top of the stack frame, so the i variable is allocated eight bytes below that in this case.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
2

Let's say that NORMALLY, if i is a local variable, it will be saved on the stack. The abstract VM of .NET is a stack based one.

I'll add that on Intel/AMD i won't be saved that way :-) Intel/AMD are little endian. So it will be 00000001 00000000 00000000 00000000

I'm mixing it a little... Now... the IL language and the .NET abstract VM are "pure" stack based, so there is a stack :-) (but there are no registers, so "pure") (I hope you know what a stack is). When the code is JITted to machine code for the computer you are using, probably i will be put in a register or on the stack.

Note that in general it's wrong wrong wrong to say that value types (or non-reference types, if you want to include managed/unmanaged pointers/references) are saved on the stack and/or in registers. They are saved where they are saved. For example value types member of a class are saved with(in) the class (so normally in the heap). Value types in yield functions, in async functions, in "normal" methods but being referenced by "closure type" anonymous functions are normally saved somewhere in the heap. But all these are reference implementations details.

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • Desktop .NET doesn't have a VM, there is a virtual architecture that MSIL targets, but this architecture isn't implemented. Instead a JIT compiler converts MSIL into native code. – Ben Voigt Oct 30 '11 at 17:14
  • @BenVoigt For VM I meant Virtual Machine not as VMWare but as "Virtual Architecture". – xanatos Oct 30 '11 at 17:17
  • @BenVoigt [Wiki](http://en.wikipedia.org/wiki/Virtual_machine) calls them `Process Virtual Machine` – xanatos Oct 30 '11 at 17:18
  • I assumed you meant like a Java virtual machine. But .NET doesn't have one. There is nothing that executes MSIL instructions. – Ben Voigt Oct 30 '11 at 17:20
  • @BenVoigt The first implementations of Mono where interpreted if I remember correctly. The existence or absence of a VM is an implementation detail. In the end you program against this "abstract" machine and then, thanks to Microsoft engineers, your code is compiled instead of being interpreted. – xanatos Oct 30 '11 at 17:26
  • You program against an architecture. A machine is an implementation. The only MSIL interpreter I know of is the .NET Micro Framework, the CLR specs for desktop specifically require a JIT IIRC. An implementation detail that violates the specification isn't a detail, it's a nonconformity. – Ben Voigt Oct 30 '11 at 18:26
  • Anyway, I don't think this question is about .NETMF or Mono. – Ben Voigt Oct 30 '11 at 18:29
0

From what I can tell, actual heap allocated references are stored as double pointers (or some equivalent) so that the garbage collector can move memory without having to affect anywhere in code that something is referenced by updating pointer being pointed to.

Mranz
  • 1,260
  • 1
  • 12
  • 20
  • The references are (in the current implementation) not double pointers, but direct pointers. The garbage collector does actually update the pointers themselves when it moves an object. – Guffa Oct 30 '11 at 17:27
  • @Guffa That smells like bad implementation to me then, because the GC would have to track all usages of the item, stack and otherwise. – Mranz Oct 30 '11 at 17:33
  • 2
    It has to do that anyway, to know which objects are used and which are not. – Guffa Oct 30 '11 at 18:06
  • Only if it isn't using a reference counting mechanism like shared pointers. – Mranz Oct 31 '11 at 17:46
  • 1
    It's not using reference counting. This might be informative: http://stackoverflow.com/questions/867114/why-no-reference-counting-garbage-collection-in-c – Guffa Oct 31 '11 at 18:57
  • I will have to look into the book. Thanks for the information. – Mranz Oct 31 '11 at 19:15