【问题标题】:would there ever be sharing parts of caller/callee stack frames?是否会共享调用者/被调用者堆栈帧的一部分?
【发布时间】:2013-06-27 08:34:44
【问题描述】:

我想知道编译器是否有可能完成这些场景?

首先我们将 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();

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

【问题讨论】:

  • 你是在谈论 RVO 吗?
  • @PlasmaHH 绝对没有

标签: c++ function memory-management compiler-construction stack-frame


【解决方案1】:

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

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

 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);
    ...
 }

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

所以,是的,可以肯定的是,当前被调用者可以访问更早的调用者堆栈帧。

【讨论】:

  • 据我所知,当函数被内联时,引用不是指针,在这种情况下,它只是它所指内容的别名,在场景#1 中,我故意声明函数没有内联排除这种情况,和你描述的机制一样,称为 RVO(返回值优化),但不是我的意思
猜你喜欢
  • 2013-10-12
  • 1970-01-01
  • 2011-01-16
  • 2015-09-08
  • 1970-01-01
  • 2014-07-10
  • 2019-10-28
  • 2021-08-06
  • 1970-01-01
相关资源
最近更新 更多