是否会共享调用者/被调用者堆栈帧的部分?

问题描述 投票:0回答:1

我想知道编译器是否可以做到这些场景?

首先我们将 SomeDataType 定义为:

struct SomeDataType{
public:
int a;
int b;
int c;
};

场景#1_关于具有如下引用参数的被调用者函数:

void doSomething(SomeDataType & input){
...
}

假设该函数不是内联的,并且只有调用函数范围内的变量被传递给程序中的该函数,并且考虑到引用不一定是指针,放置输入参数的内存部分在堆栈之间共享任何调用者函数的帧和“doSomething”被调用者函数的堆栈帧,以便“doSomething”可以像寻址其本地范围内的任何局部变量一样寻址该参数,即通过向基指针添加偏移量来确定其起始地址堆框架。

场景#2_这对我来说似乎不太可能,但无论如何;关于返回“SomeDataType”类型结构的被调用函数:

SomeDataType doSomething(){
SomeDataType someStruct;
...
return someStruct;
};

结构“someStruct”所在的内存部分在任何调用者的堆栈帧和“doSomething”被调用者函数的堆栈帧之间共享,因此请考虑调用者函数中的以下语句:

SomeDataType TheStruct=doSomething();

在调用者的范围内使用“TheStruct”会导致使用与被调用者范围中的“SomeStruct”所在的内存相同的部分,这意味着基本上被调用者函数不会在任何地方复制“someStruct”,即使复制是必要的,就像当在调用者函数中存在如下所示的语句,表明目标不是调用者作用域中的结构:

*pntrToSomewhere=doSomething();

调用者有责任将该共享部分的内容复制到该指针指示的位置。

c++ function memory-management stack-frame
1个回答
0
投票

如果将引用(或指针)传递给调用函数(调用者)中的局部变量,那么它将位于调用者堆栈帧上。请注意,我不知道任何架构,如果你掀起地毯并看看它在漂亮的表面下实际上是如何工作的,引用实际上并不是指针。该标准并不要求这样做,但至少在大多数架构中它是如何实现的 - 我实际上有兴趣了解如何实现它 - 但我没有花太多时间考虑它。

具有

struct
class
返回类型的函数的典型行为是它传递一个指向临时空间的“额外”参数来存储返回类型,例如:

 T myfunc(int x, int y)

 ...

 void foo()
 {
    ...
    T x = myfunc(2, 18);
    ...
 }

将显示为相同(隐藏参数不一定是第一个参数 - 但它几乎肯定是第一个或最后一个):

 void myfunc(T& hidden, int x, int y)

 void foo()
 {
    ...
    T x;
    myfunc(x, 2, 18);
    ...
 }

实际上,堆栈帧并不是共享的,就像“我们传递位于或更早的调用者的堆栈帧中的指针一样”。

所以,是的,当然可以从当前被调用者访问早期调用者堆栈帧。

© www.soinside.com 2019 - 2024. All rights reserved.