有趣的节目行为

Asc*_*hem 0 c++

所以我有一个小程序

#include <iostream>
using namespace std;

void lol() {
    cout << "How did we get here?"<<std::endl;
}

int main()
{
   long a, b, z[10];
   cin >> a >> b;
   z[a] = b;
}
Run Code Online (Sandbox Code Playgroud)

您可以在此处通过在线编译器运行它

该程序没有任何目的,但它有一个错误或功能 - 我不知道它是什么.所以,如果你写这样的东西, main 13 2015你可能什么也得不到,但是如果你输入两个幻数13,4196608你就会得到一个错误.此外,程序执行功能void lol()并打印线How did we get here?.

我跑了nm ./main,发现我的函数void lol()的地址0000000000400900等于4196608(数字系统的基数是10).

这意味着程序由于某种原因"跳转"到该地址并执行该功能void lol().而且,如果我改变第一个数字,什么都不会发生. main 10 4196608,main 11 4196608,main 12 4196608,main 14 4196608,main 15 4196608-都是一样的,没有错误,但只要我进入数字13我得到这个有趣的现象.

谁能解释一下这里发生了什么?

Bas*_*tch 7

如果输入for a是一个大于9的数字(或负数),则表示您正在访问z[a]错误(超出索引,缓冲区溢出),因为您声明了一个数组long z[10]

这是典型的未定义行为(UB).

UB 非常糟糕,看到我的这个答案,或者更多背景:

解释一些实际未定义行为的唯一方法是深入了解所有特定于实现的细节(编译器,优化,操作系统,机器代码,处理器等......).你可能会花费数年时间.(可能在您的情况下,调用堆栈上的返回地址已被lol函数地址覆盖).

  • 我的猜测是你正在搞乱异常系统使用的堆栈展开代码. (2认同)
  • 我不知道`ret`指令从堆栈中获取地址,因此@ basile-starynkevitch猜测更准确. (2认同)