Isn't the nature of stack allocation such that if a frame has been popped out, that frame is essentially "lost" ? So a frame preservation scheme would not work, unless I missed something.
Here's a recap of the the situation :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | B()
{
C();
// struct `Sb` allocated on stack
}
C()
{
// struct `Sc` allocated on stack
}
A()
{
B();
// structs `$B.Sb` and `$C.Sc` being referenced, and work done upon them
}
|
And here's a visualization of the stack, the way I understand it (stack grows towards the bottom):
1) Inside
C() scope, after
A() -> B() -> C() chain of calls.
| | ....... | A frame
+---------+
| ..$Sb.. | B frame
+---------+
| ..$Sc.. | C frame
+---------+ <-- STACK TOP --
|
2) Inside
A() scope, after returns from
C() and
B().
| | ....... | A frame
+---------+ <-- STACK TOP --
| ..$Sb.. | B frame
+---------+
| ..$Sc.. | C frame
+---------+
|
At this point,
$B.Sb and
$C.Sc can be referenced, and the data they hold could be worked upon without problems.
But now suppose that a new
D() call has been inserted in function
A() :
| A()
{
B();
D();
// structs `$B.Sb` and `$C.Sc` are being referenced
}
|
3) Now, the frame of
D() will overwrite the frame of
B(), thus rendering the contents of
$B.Sb invalid (and potentially
$C.Sc too).
| | ....... | A frame
+---------+
| ....... | D frame
+---------+ <-- STACK TOP --
| ..$Sc.. | C frame
+---------+
|
Technically,
$B.Sb could still be available, provided that
$B.Sb is placed high enough in the stack, so that the frame of
D() could not reach and overwrite it.
But there's no guarantee of that, and it's not at all clear how to make that work in the general case.