Assume we created an instance of a class in the stack. I understand that the compiler gives it a specific amount of memory depending on the types and amount of fields in that instance. But I am confused about the instance methods. I assume they have their own stack frame.
What I don't understand:
Where the stack frame of the instance method is located? Are they located inside of the instance stack frame or they are stored elsewhere?
Is there only one instance method stack frame created for many instances of the class
if so, then what if two objects of the same class at the same time will call the same function from different threads?
Like normal functions, there are multiple pieces of memory associated with member functions in C++. First, there's the actual assembly instructions that make up the member function, which is usually put into the code segment and shouldn't be of any concern. Second, every time that member function is invoked, additional stack space is reserved for all of the local variables ("automatic objects") inside of that call, which is cleaned up when the call returns. I should specifically point out that functions don't have some fixed preallocated memory for their stack space - if a function is recursive, for example, you might have multiple stack frames active for that function at the same time. Rather, there's as many stack frames as needed.
When you declare a local variable of class type in C++, you only get the memory for the object itself. No extra memory is allocated to hold the member functions of that object - as mentioned above, the member function memory is either placed away in the data segment or is allocated as needed when you call the member functions. Specifically, if you call a member function on the object you've declared, then the program will allocate a new stack frame for that member function, call the function, and clean up the memory when the function returns. There is no extra "premium" paid for having member functions; they don't actually influence the size of the object (though having one or more virtual functions in your class may add a one-time cost to the size of your object).
Of course, this is all implementation-dependent; an implementation in principle could allocate extra space to store the member functions inside the object, but to the best of my knowledge no standard C++ implementations will do this. (If you know what a vtable is, the object might have a vtable pointer, but not all the vtable entries).
Hope this helps!
1. Where the stack frame of the instance method is located? Are they located inside of the instance stack frame or they are stored elsewhere?
There's no such thing like an instance stack frame. Stack frames are created in the actual execution thread's call stack.
2. Is there only one instance method stack frame created for many instances of the class
See my answer for 1.. There are different call stacks per thread, yes.
3. if so, then what if two objects of the same class at the same time will call the same function from different threads?
As said before, there are different stack frames created for each thread. There aren't any call stack frames per instance. It's only the different implicitly passed this pointers, that distinguish the instances accessed.
A method is essentially a "chunk" of opcodes (machine operations), located in the (read-only) code-section of the executable image.
So methods have nothing to do with the stack (in terms of the memory in which they reside).
Nevertheless, they do access the stack whenever they perform operations on local variables.
An instance of a class does not "contain" the class methods, but only the class attributes (the variables that you define in the class), and possibly a pointer to the V-Table of the class (if you define one or more virtual functions in the class or in one of its base-classes).
As long as a method operates on non-static local variables or non-static member variables, it is thread-safe, as these variables are allocated in the stack every time the method is invoked, and every thread has its own stack (its own separate area within the entire stack, to be more accurate).
Once a method operates on variables that are not allocated in the stack (static local variables, static member variables, static global variables or non-static global variables), it becomes thread-unsafe and has to be treated as such (typically with appropriate OS resources, such as semaphores, mutexes, etc).
Also, keep in mind that an inline function/method call may not create a stack frame at all.
And the che compiler may inline a funcition call for optimization.
Related
is there any reason why we should not store strings as storage in a function? I do not get the purpose of using it.
If anyone can explain it's greatly appreciated.
Variables declared as function parameters are either stored at a call data or memory data location.
Variables declared inside functions, are stored in a memory data location.
Every operation in a smart contract costs you money. So you have to be careful when you design a smart contract. Your variables that set in a storage will cost you no matter what, but variables inside functions will cost you when your functions are being called. It is kinda paid as you go.
Variables that are declared as a state are always stored in the storage.
When creating state variables in any application, you have to be very careful not to modify them. Because if you modify them in one part of your code, another part of your code may not give you the desired result, and you will create a lot of bugs.
Imagine, you identified your function as public, and variables and arguments are stored in storage. So anyone who calls your function will modify your state variables. To keep the state variables safe, inside functions we copy them into memory and use this copied value.
Hi i want to ask how the EBP and ESP registers are initialized and updated during program execution.
I have an image below and the author explains that when entering a new function, first the arguments are pushed onto the stack shown in the yellow region, then the base pointer EBP is updated and the base pointer of the previous function stored, followed by stack allocating more resources for local variables and return addresses.
I want to know wouldn't it be easier to simply update the base pointer when entering the new function, then allocate memory for the previous function's base pointer register address, followed by the arguments, local variables and return value? Instead of having the EBP in the middle of a stack frame for a function.
My other question is, where exactly does the return address value point to in the previous function, is it at the end of the previous function, or the start of the previous function?
My other question is, what significance does storing the previous function base pointer register if you already store the return address of the previous function?
The idea i get from pointers is that you essentially just want to use them as a reference for accessing resources local to a function, you can do with the return address
Thanks
To return from a function you need to restore (at least) two things.
One is where the instruction pointer is, what the next instruction you are running it located at.
The other is where the stack pointer is, where the data you are operating is.
(Depending on calling convention, registers may also have to be reset, but I don't know details here).
The return address -- the instruction pointer -- points to where the code should continue executing when returned from the call. This isn't usually either the start or end of the calling function, but rather the "next instruction" after the call. (But not really; it points to the code that handles the return from the function, which in some calling conventions does real work).
The code calling a function has to update the stack pointer so that the called function knows where its on-stack arguments are, and provide enough information for the called function to return.
The function called has no need to do that internally. It (well, the compiler writing it knows) what variables it has put on the stack, and how big they are. The set of variables on the stack may vary over time during the body of the function. So updating the stack pointer is pointless, and would even make offset calculations a bit more complex (as they keep on changing, instead of being constant for a given "variable") and confusing for an assembly writer.
Code that accesses the stack does so with an offset regardless. Not changing the stack pointer is doing less work than changing the stack pointer, and doing less work usually is faster than doing more work.
So you leave the stack pointer alone, unless you need to change it.
The return address is useless for accessing mutable data. The return address points at usually read-only machine code, not at mutable state on the stack.
Now, there are plenty of calling conventions in the wild. Many of them do slightly different things. Which arguments go on the stack, which are stored in registers, what kind of arguments go where, and who resets the stack pointer (the caller or the callee) can vary, among other things.
As objects are created from same class. Each object contains the variable defined in the class except those which are defined in the methods of that class. Variable in functions of the same object are shared memory right? If we have a function where we create an object of the same class, where will be the reference reside? Isnt that reference be shared too?
Methods are no different from any other function with regard to memory use: local variables are created when execution reaches their declaration, and (unless static) they are destroyed, and their memory reclaimed, when execution leaves the block it. (This happens, at latest, when the function returns.) There is no connection to the this object or any of its members. Nor does the variable having the same type as the method’s class make any difference.
In some sense, that does make the memory “shared”: it will be rapidly reclaimed and (typically) reused. But that’s nothing special, and don’t think that it means more than it does: if a method is recursive, or invoked concurrently by more than one thread, each copy has its own locals—again, just like any other function.
Finally, any function or method can allocate memory dynamically; the lifetime and sharing of the allocated object may be unrelated to that of the variable used to refer to it.
I'm currently adapting some example Arduino code to fit my needs. The following snippet confuses me:
// Dont put this on the stack:
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
What does it mean to put the buf variable on the stack? How can I avoid doing this? What bad things could happen if I did it?
The program stack has a limited size (even on desktop computers, it's typically capped in megabytes, and on an Arduino, it may be much smaller).
All function local variables for functions are stored there, in a LIFO manner; the variables of your main method are at the bottom of the stack, the variables of the functions called in main on top of that, and so on; space is (typically) reserved on entering a function, and not reclaimed until a function returns. If a function allocates a truly huge buffer (or multiple functions in a call chain allocate slightly smaller buffers) you can rapidly approach the stack limit, which will cause your program to crash.
It sounds like your array is being allocated outside of a function, putting it at global scope. The downside to this is there is only one shared buffer (so two functions can't use it simultaneously without coordinating access, while a stack buffer would be independently reserved for each function), but the upside is that it doesn't cost stack to use it; it's allocated from a separate section of program memory (a section that's usually unbounded, or at least has limits in the gigabyte, rather than megabyte range).
So to answer your questions:
What does it mean to put the buf variable on the stack?
It would be on the stack if it:
Is declared in function scope rather than global scope, and
Is not declared as static (or thread_local, though that's more complicated than you should care about right now); if it's declared static at function scope, it's basically global memory that can only be referenced directly in that specific function
How can I avoid doing this?
Don't declare huge non-static arrays at function scope.
What bad things could happen if I did it?
If the array is large enough, you could suffer a stack overflow from running out of available stack space, crashing your program.
Whcih occupies memory, a class or an object? And, is that at compile or execution time?
Thanks.
During compilation, the layout of memory is an implementation detail--you don't need to know or care.
During runtime, however... in C++, classes define types but (unless you activate RTTI which allows limited introspection into classes) don't generally occupy any memory themselves1--they're just the frameworks for the construction and destruction of objects. Their methods, however--the constructors, destructors, instance methods, and class methods, occupy some portion of executable memory, but compilers can and do optimize away any such methods that are not used in the program.
Instances of types (that is, objects as well as primitives like int variables) occupy the bulk of memory in C++, but for their member functions they refer back to their classes. Exactly how much memory an instance of a particular class uses is entirely and utterly an implementation detail, and you should generally not need to care about it.
1 Even then, the classes themselves don't use the memory, but their associated std::typeinfo instance does. But again, this is generally implementation-y stuff and not the sort of thing even wizened programmers pay much attention to.
The object instance is the one which occupies memory at execution time since a class is the blueprint of the object.
Also, in C++ there are static variables, local variables and global variables which also occupies memory.
Static, local and global variables are stored in BBS data segment, while objects are stored either in heap or in stack.
Objects are the instances of class, while class definition is used by compiler to create an object by it's class description. Class is like an instruction of "how to build table by yourself" that occupies only the paper it's written on, while an object is the real table made by yourself according to the instruction, that occupies the real space.