为什么这样做?这是一个小例子,但它甚至可以用于更复杂的项目

jos*_*shj 3 c++

#include <cstdio>
class baseclass
{
};

class derclass : public baseclass
{
public:
    derclass(char* str)
    {
        mystr = str;
    }
    char* mystr;
};
baseclass* basec;

static void dostuff()
{
    basec = (baseclass*)&derclass("wtf");
}

int main()
{
    dostuff();
__asm // Added this after the answer found, it makes it fail
{
    push 1
    push 1
    push 1
    push 1
    push 1
    push 1
    push 1
    push 1
    push 1
    push 1
}
    printf("%s", ((derclass*)basec)->mystr);
}
Run Code Online (Sandbox Code Playgroud)

Man*_*agu 10

啊.这是"不要做这个"的例子之一.在dostuff,您创建一个临时类型derclass,获取其地址,并设法将其传递到外部dostuff(通过分配basec).创建临时文件的行完成后,通过该指针访问它会产生未定义的行为.它的工作原理(即你的程序打印"wtf")肯定是平台依赖的.

为什么它在这个特定的实例中有效?要解释这一点需要深入研究而不仅仅是C++.您创建一个临时类型derclass.它存放在哪里?可能它被存储为堆栈中非常短暂的临时变量.你拿它的地址(堆栈上的一个地址),然后存储它.

稍后,当您去访问它时,您仍然有一个指向堆栈部分的指针.由于没有人来过并重复使用堆栈的那一部分,因此对象的残余仍然存在.由于对象的析构函数没有做任何事情来消除内容(毕竟,只是指向静态数据中存储的"wtf"的指针),你仍然可以读取它.

尝试插入在调用dostuffprintf调用之间占用大量堆栈的东西.比如说,调用一个factorial(10)递归计算的函数.我敢打赌,printf不再有效.

  • 但这是未定义行为的优点:它可能会做任何事情.它甚至可能使程序工作.但你永远不会知道. (4认同)

aJ.*_*aJ. 6

basec = (baseclass*)&derclass("wtf");
Run Code Online (Sandbox Code Playgroud)

在函数中遇到临时对象时derclass立即创建和销毁.因此,您的指针指向无效对象.;dostuff()basec