Does a stack frame really get pushed onto the stack when a function is called?

旧城冷巷雨未停 提交于 2019-12-04 19:55:01

Regarding your first question:

The creation of the object has nothing to do with the allocation of the data itself. To be more specific: the fact that the object has its reserved space on the stack doesn't imply anything about when its constructor is called.

Does this mean that the total memory for a stack frame is not allocated all at once, but rather block by block as the variable declarations are encountered?

This question is really compiler specific. A stack pointer is just a pointer, how it is used by the binary is up to the compiler. Actually some compilers may reserve the whole activation record, some may reserve just little by little, some other may reserve it dynamically according to the specific invocation and so on. This is even tightly coupled with optimization so that the compiler is able to arrange things in the way it thinks is better.

Does this mean when a function is called, a stack frame may not be created at all ? Does this also imply that a stack frame may differ in size due to the use of registers ?

Again, there is no strict answer here. Usually compilers rely on register allocation algorithms that are able to allocate registers in a way that minimizes "spilled" (on stack) variables. Of course, if you are writing in assembly by hand, you can decide to assign specific registers to specific variables throughout your program just because you know by their content how you want to make it work.

A compiler can't guess this, but it can see when a variable starts to be used or is no longer needed and arrange things in a way that minimize memory accesses (so stack size). For example, it could implement a policy such that some registers should be saved by the called, some others by the callee and assign or whatever.

  1. Constructing a C++ object has very little to do with acquiring memory for the object. In fact, it would be more accurate to say "reserving memory", since in general, computers do not have little teams of RAM-builders which spring into action every time you ask for a new object. The memory is more or less permanent (although we could quibble about VM). Of course, the compiler has to arrange for its program to only use a particular range of memory for one thing at a time. That may (and probably does) require it to reserve a range of memory prior to the object's existence, and avoid using it for other objects until some time after the object's disappearance. For efficiency, the compiler may (even in the case of objects with dynamic storage duration) optimize reservations by reserving several blocks of memory at once, if it knows it will need them. In any event, when C++ talks about "constructing an object", it means just that: taking a range of memory with undefined contents, and doing what is necessary to create the representation of the object (and whatever else in the state of the world is implied by the creation of the object, which might not be limited to a particular hunk of memory.)

  2. There is no requirement for stack frames to exist. There is no requirement for a stack to exist. That's all up to the compiler. Most compilers do generate code which uses a stack, of course, and good compilers will figure out when it is possible to abbreviate or even omit a stack frame. So, yes, frames may vary in size.

You are absolutely right, a stack frame is not required. Stack frames are a quick and dirty solution to the problem of managing the local space, easier to debug than to manage changes in the stack pointer during the course of the function. If there is a need for the stack within the function it is easier to just adjust the stack pointer on entry and restore it on return.

This is also not black and white, compilers are programs like any other program, and if you dont already know then you will come to realize that given any number of programmers you are going to get multiple solutions to the same problem. Even if the number of programmers is one that one person may choose to solve the problem over and over again until they are satisfied and/or for whatever reason may choose to release the various versions. The use of the stack is very common for local variables, it is really how you do it but that does not mean you have to use a stack frame created on entry and restored on return.

And as you have learned in your classes and is very easy to see through experiments (compile some simple functions, with various levels of optimization from no optimization to some) that for example gcc wont use the stack unless it has to. We are talking arm here right where the normal calling convention is register based (there is nothing that says the compiler author(s) have to follow that convention, it is possible to use stack based on arm if a compiler choose to do that). Processors where the normal convention is stack based since the code is already dealing with the stack it may choose to use a stack frame anyway. It is likely that in those cases the stack based convention is used because the processor lacks general purpose registers and relies more on the stack than other processors with more registers, which means that processor likely needs the stack often not just for the calling convention but for most of the local storage.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!