Bob Langelaan <
bobl...@gmail.com> writes:
> On Saturday, April 16, 2016 at 4:38:24 PM UTC-7, Alf P. Steinbach wrote:
>> On 17.04.2016 01:05, Jens Thoms Toerring wrote:
<snip>
>> > Actually, neither the C nor C++ standard even mandate that there's a
>> > stack at all
>>
>> Wrong (to the degree that nonsense can be said to be wrong, but it might
>> more correct to say that it's not even wrong).
>>
>> Possibly you mean that they don't specify the stack implementation,
>> whether it's a linked list or an ordinary machine stack or what.
>>
>> But both languages support recursive function calls with automatic local
>> variables: in the general case this is impossible without a stack.
>>
>>
>> > how could be there a requirement on how things have to be organized
>> > on the stack?
>>
>> There is the general stack requirement, last-in-first-out, which is the
>> definition of a stack.
>>
>> However. this applies, as a logical necessity, to allocations of
>> function call frames, not to allocations of individual local variables.
>>
>> I suspect the OP mistakenly thought the stack behavior for allocation
>> was required for individual automatic storage local variables, since
>> their constructor and destructor calls are in LIFO order.
<snip>
> Thank you to all the people who have replied.
>
> I would like to ask a question in regards to the last paragraph that
> Alf posted. If I interpret it correctly, that even though "constructor
> and destructor calls are in LIFO order", I should not assume that the
> automatic local variables are in fact stored on some form of a stack?
There's a lot of confusion here. Alf is not saying that. In fact he's
saying that automatic local variables will be on a stack. His point is
that just because this might be the case, it is not the mechanism by
with constructor and destructor calls are maintained. Within a function
the local object can be positioned as the compiler likes, provided the
constructors and destructors are called correctly.
But (and this is an aside) there is no guarantee that anything will be
stored in a stack-like structure. In the general case you do need a
LIFO structure for function calls, but if the functions are not
(mutually) recursive, only the return addresses need to be stored in a
stack like structure -- function locals could be in statically allocated
storage. And if, like in your example, there is only one function, you
don't need even that small stack-like structure.
Now, from a practical point of view, there is no reason for a compiler
to abandon what it must do in the general case (fully mutually recursive
function calls) and do something special when it detects that it could,
so stack allocation is to be expected, but it's not guaranteed by the
language.
> If this is the case, it seems to me that any other form of data
> structure would be awkward to use/implement and still have the LIFO
> order maintained.
When the compiler inlines a function call, one of the things it is doing
is optimising away a stack frame, but any automatic objects in the
function body must still behave correctly with the constructors and
destructors called in the right order. This is not very different to
what happens when entering a block with declared objects.
Remember that construction is really initialisation. The compiler will
often allocate one area for an object and then call the constructor many
times to simulate objects coming and going:
void f()
{
...
while (...) {
A a(42);
B b(43);
...
}
...
}
might compile to
void f()
{
space big enough for b;
space big enough for a;
...
while (...) {
call A's constructor(&a, 42);
call B's constructor(&b, 43);
...
call B's destructor;
call A's destructor;
}
...
}
Here the constructor/destructor order is maintained with no relation to
stack pushing and popping or relative addresses.
--
Ben.