繁体   English   中英

const& args 存储在哪里?

[英]Where is the const& args stored?

这是 function 定义

const int& test_const_ref(const int& a) {
  return a;
}

并从main调用它

int main() {
  auto& x = test_const_ref(1);
  printf("%d, %p\n", x, &x);
}

output 如下

 ./debug/main
>>> 1, 0x7ffee237285c

这是test_const_ref的反汇编代码

test_const_ref(int const&):
    pushq  %rbp
    movq   %rsp, %rbp
    movq   %rdi, -0x8(%rbp)
    movq   -0x8(%rbp), %rax
    popq   %rbp
    retq

问题是:变量x别名或我传递给 function test_const_ref的数字1存储在哪里?

该代码表现出未定义的行为- function test_const_ref返回一个对临时的引用,该引用一直存在到完整表达式( ; )的末尾,之后对其的任何取消引用都会访问一个悬空引用。

出现工作是UB的常见表现。 程序仍然是错误的。 例如,通过优化Clang 12 -O2打印: 0

注意 - function test_const_ref本身没有错误(除了设计错误)。 UB 在main中,在调用printf期间,悬空int&的取消引用发生。

临时int准确存储的位置是实现细节 - 但在许多情况下(在调试版本中,当 function 未内联时),它将存储在堆栈中:

main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     dword ptr [rbp - 12], 1      # Here the 1 is stored in the stack frame
        lea     rdi, [rbp - 12]
        call    test_const_ref(int const&)
        mov     qword ptr [rbp - 8], rax
        mov     rax, qword ptr [rbp - 8]
        mov     esi, dword ptr [rax]
        mov     rdx, qword ptr [rbp - 8]
        movabs  rdi, offset .L.str
        mov     al, 0
        call    printf

因此,任何后续使用返回的引用都将访问[rbp - 12]处的 memory ,这可能已经被重新用于其他目的。


另请注意,编译器实际上并未从 C++ 代码生成程序集; 它仅使用 C++ 代码来理解意图,并生成另一个程序来生成预期的 output。 这被称为假设规则 在存在未定义行为的情况下,编译器不受此限制,可能会生成任何output,从而使程序变得毫无意义。

已经给出了很好的答案,但是wrapperm 在这里很好地解释了这个主题。 在我知道的大多数实现中,它将存储在堆栈中。

1. function

该语言没有定义 arguments 到函数的存储位置。 针对不同平台的不同 ABI 对此进行了定义。

通常,在进行任何优化之前,function 参数存储在堆栈中。 参考在这方面没有什么不同。 实际存储的是指向 object 的指针。 这样想:

const int* test_const_ref(const int* a) {
  return a;
}

2.临时

如果你要声明一个变量int foo; 并调用test_const_ref(foo) ,您知道结果将引用foo 由于您使用临时调用它,因此所有赌注都已关闭:正如@fabian 在评论中指出的那样,该语言仅保证该值存在直到赋值语句结束。 然后

在实践中,在您的情况下:为临时 integer 1分配堆栈空间的编译器将x引用该位置,并且在定义x之前不会将其用于其他用途。 但是,如果您的编译器优化了该堆栈分配 - 例如通过寄存器传递1 - 那么x没有可引用的内容并且可能包含垃圾。 它甚至可能是未定义的行为(对此不太确定)。 如果你幸运的话,你会得到一个关于它的编译器警告(GodBolt.org)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM