ECMA-335, I.12.3.2.4 states the following:
Part of each method state is a local memory pool. Memory can be explicitly allocated from the local memory pool using the
localloc
instruction. All memory in the local memory pool is reclaimed on method exit, and that is the only way local memory pool memory is reclaimed (there is no instruction provided to free local memory that was allocated during this method invocation). The local memory pool is used to allocate objects whose type or size is not known at compile time and which the programmer does not wish to allocate in the managed heap. Because the local memory pool cannot be shrunk during the lifetime of the method, a language implementation cannot use the local memory pool for general-purpose memory allocation.
Where does CLR allocate this memory pool? Is it managed heap, thread stack, etc?
Stack and Heap The Common Language Runtime (CLR) allocates memory for objects in these parts. Stack is a simple LIFO(last-in-first-out) structure. Variables allocated on the stack are stored directly to the memory and access to this memory is very fast, and its allocation is done when the program is compiled .
Dynamic memory allocation is the process of assigning the memory space during the execution time or the run time. Reasons and Advantage of allocating memory dynamically: When we do not know how much amount of memory would be needed for the program beforehand.
Methods are stored somewhere else in the memory. Notice that methods are per-class, not per-instance. So typically, the number of methods doesn't change over the run-time of a program (there are exceptions). In traditional models, the place where the methods live is called the "code segment".
This is all intentionally vague because it is a strong implementation detail that the CLI spec doesn't want to nail down. It peeks through the cracks in the MSDN article for Opcodes.Localloc though:
StackOverflowException is thrown if there is insufficient memory to service the request.
There's only one way you ever get SOE: it requires allocating from the stack.
The C# language is less shy about where it gets allocated, it uses the stackalloc keyword. A sample program:
class Program {
static unsafe void Main(string[] args) {
int* p = stackalloc int[42];
}
}
Produces this IL:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 9 (0x9)
.maxstack 8
IL_0000: ldc.i4.s 42
IL_0002: conv.u
IL_0003: ldc.i4.4
IL_0004: mul.ovf.un
IL_0005: localloc // <=== Here
IL_0007: pop
IL_0008: ret
} // end of method Program::Main
Which produces this machine code at runtime:
02E42620 push ebp
02E42621 mov ebp,esp
02E42623 sub esp,8
02E42626 mov dword ptr [ebp-4],esp
02E42629 mov dword ptr [ebp-8],6A029823h
02E42630 mov eax,esp
02E42632 test dword ptr [esp],esp
02E42635 sub eax,0A8h // <=== Here
02E4263A mov esp,eax
02E4263C mov dword ptr [ebp-4],esp
02E4263F cmp dword ptr [ebp-8],6A029823h
02E42646 je 02E4264D
02E42648 call 730CA5C0
02E4264D lea esp,[ebp]
02E42650 pop ebp
02E42651 ret
The sub eax,0A8h
instruction subtracts 0xa8 = 168 = 42x4 bytes from the ESP register (the stack pointer), the mov esp,eax
instruction adjusts the stack pointer. So yes, this definitely comes from the stack.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With