c++ - 为什么这行得通?这是一个小例子,但它甚至适用于更复杂的项目

标签 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);
}

最佳答案

呃。这是那些“永远不要这样做”的例子之一。在 dostuff 中,您创建了一个 derclass 类型的临时对象,获取其地址,并设法将其传递到 dostuff 之外(通过将其分配给 basec)。创建临时文件的行完成后,通过该指针访问它会产生未定义的行为。它的工作原理(即您的程序打印“wtf”)当然取决于平台。

为什么它在这个特定实例中起作用?要解释这一点,需要深入研究而不只是 C++。您创建一个 derclass 类型的临时对象。它存储在哪里?可能它作为一个非常短暂的临时变量存储在堆栈中。您获取它的地址(堆栈中的地址)并存储它。

稍后,当您访问它时,您仍然有一个指向堆栈的那部分的指针。由于此后没有人出现并重新使用堆栈的那部分,因此该对象的残余物仍然存在。由于对象的析构函数不会执行任何操作来清除内容(毕竟,它只是指向存储在静态数据中某处的“wtf”的指针),您仍然可以读取它。

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

关于c++ - 为什么这行得通?这是一个小例子,但它甚至适用于更复杂的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1444112/

相关文章:

c++ - 如何在 Windows 上检测 QtCreator 中的内存泄漏?

c++ - 在 C++ 中为指针 vector 创建自定义排序时遇到问题

c++ - vector 指针<unique ptr> 上的 Sysmalloc 错误第二次推回

c++ - Boost 测试设置错误 : memory access violation

c++ - 使用 ITK 计算图像的中值

c++ - 在 C++ 中的微 Controller 上执行转换为较小类型的推荐方法

c++ - 使用 C++ 获取 Windows 文件信息

c++ - SDL2 Hello World 教程因错误而关闭

c++ - 在类的私有(private)部分中为复制构造函数定义原型(prototype)如何防止类的复制?

c# - 将 C++ 特定功能映射到 C++/CLI