【问题标题】:Unexpected output while sending a pointer by reference通过引用发送指针时出现意外输出
【发布时间】:2021-08-29 23:51:49
【问题描述】:

所以,我尝试了一些事情,并决定有意从应该返回 int 的函数中删除 return 语句。

我的猜测是,函数会返回一个垃圾值,程序会正常终止。

但是,程序陷入了无限循环。这是一个错误吗?还是我错过了什么?

我使用的编译器是 G++,GCC 版本 9.3.0,带有 GNU-G++-17 和 GNU-G++-14

#pragma GCC optimize("O1")
#include <iostream>

int f(int* &a)
{
    std::cout << *a;
    // return 0;
}

void solve()
{
    int *p = new int{7};
    f(p);
    delete p;
}

int main()
{
    solve();
}

编译器输出

777777777777777777777777777777777...(until it crashes...)

上述代码的 ideone 链接:https://ideone.com/j9m24N

PS:- O1O2O3Ofast 的编译指示会发生这种情况,但O0 不会发生这种情况

我知道我们应该提供一个 return 语句,但我有兴趣知道我们得到这个输出的原因。

【问题讨论】:

  • 为什么问题在未定义行为的情况下毫无意义。 “这是虫子吗?”是的,这是程序中的一个错误。
  • 尽管有 UB,但 GCC 如何选择优化它仍然很有趣。如果您在switch-case 语句中不使用break;,但在此处的两个函数之间,它基本上会产生相同的问题。虽然不是特别有用,因为 UB 仍然很有趣
  • @Lala5th 没有return,没有asm ret 命令,f 落入solve 得到无限递归。
  • 这似乎在clang 中处理得更好,而不是不编译(如 msvc),或者优化不产生返回(就像你在 gcc 中看到的那样,仍然不知道为什么只虽然打开了优化),它会生成ud2(undefined instruction),因此程序不会失败。
  • @S.M.奇怪的是,它只通过优化来做到这一点。不确定这是有意的还是只是优化器之间的一些奇怪的游戏以及在 gcc 中如何处理 void 返回函数中的隐式返回语句

标签: c++ pointers g++


【解决方案1】:

这是一个错误吗?

是的。这是您的程序中的一个错误。

还是我错过了什么?

是的。您缺少 return 声明。

为什么我们会得到这个输出。

因为程序的行为是未定义的。这解释了 C++ 程序员需要了解的有关程序行为的所有内容,并且是我们在 C++ 语言范围内所能了解的所有内容。

我的猜测是,该函数会...

当程序的行为未定义时,您不能假设会有任何特定的行为。


要了解特定编译程序的作用,您需要阅读编译器生成的程序集。我能够重现该行为,这是一个简化:

f(int*&):
        ... instructions ...
solve():
        ... instructions ...
        call    f(int*&)

函数f 不包含ret 指令或任何其他会跳转到其他地方的指令。因此,执行继续到恰好是函数solve 的第一条指令的下一条指令。在solve 的末尾,我们调用f,这是我们开始的地方。我们最终得到了无限递归。

【讨论】:

    猜你喜欢
    • 2020-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多