gpt4 book ai didi

c++ - 在此解决方案中,void(** rptr)()和main()中的调用如何工作以在C++中打印没有循环的1-100?

转载 作者:行者123 更新时间:2023-12-01 14:39:28 26 4
gpt4 key购买 nike

在这个Quora答案中,我偶然发现了这段代码,想了解发生了什么:How can I print 1 to 100 in C++ without a loop, goto or recursion?

我问我的程序设计老师,他说他对alloca()不太熟悉,但是他确定该程序具有未定义的行为,所以我最好对SO进行询问。
值得一提的是,有关Quora的答案中的OP并不能保证它可以在其他人的系统上运行。

我很难理解void(**rptr)()的功能以及main()中的调用是如何工作的,为什么要使用* 200?。

#include <iostream>
#include <stdlib.h>
int num;
void(**rptr)();
void foo() {
if(num >= 100) exit(0);
std::cout << ++num << std::endl;
*rptr++ = foo;
}
int main() {
rptr = (void(**)())alloca(sizeof(*rptr) * 200) - 1;
foo();
return 0;
}

最佳答案

这是一个利用未定义行为的骇客技巧。分析未定义的行为是毫无意义的,但有时挖掘并找出原因很有趣。

基本上,正在发生的是alloca(...)正在分配足够的内存以在堆栈上存储200个函数指针。到目前为止,很特别,但还不错。但是关键是末尾的-1-它的返回内存是此存储之前的一个。因此,rptr将堆栈指向一个未知位置。

然后调用foo。在foo的末尾,我们将foo的地址写入rptr。但是rptr是有效内存之前的一个,因此我们要覆盖其他内容。

碰巧的是foo返回的返回地址(应该是main)。因此,它基本上不“返回”到main的开头,而不是返回foo。一直重复到到达导出为止。

其基本上是适度控制的堆栈粉碎。并且仅适用于具有调用约定的体系结构,其中将返回地址放入此庄园的堆栈中。

关于c++ - 在此解决方案中,void(** rptr)()和main()中的调用如何工作以在C++中打印没有循环的1-100?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61520210/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com