毁掉多态:篡改虚函数表指针 (vptr)#

#include <iostream>
#include <cstring>

class Entity {
public:
    virtual void SayName() { std::cout << "I am Entity" << std::endl; }
};

class Player : public Entity {
public:
    void SayName() override { std::cout << "I am Player" << std::endl; }
};

void Print(Entity* e) {
    e->SayName(); // 强制程序通过虚表查找
}

int main() {
    Entity base;
    Player p1;

    std::cout << "Before memcpy: ";
    Print(&p1); // 应该输出 I am Player

	//base复制给p1,但是p1的虚函数表却指向的是Entity的
    // 暴力覆盖!把 base 的内存(包含 Entity 的 vptr)强行塞进 p1
    std::memcpy(&p1, &base, sizeof(Entity));

    std::cout << "After memcpy:  ";
    Print(&p1); // 这次,它一定会输出 I am Entity!

    std::cin.get();
}

内存错位#

#include <iostream>
#include <cstring>

struct BaseA {
    int a = 111;
};

struct BaseB {
    int b = 222;
};

// Child 同时拥有 a 和 b,继承顺序决定内存顺序,这里先BaseA-->BaseB-->自己的成员
//在内存里,Child 对象是一块连续的砖,布局如下(假设每个 int 占 4 字节):
// 字节偏移  内容  属于谁
// 0    int a(111)  BaseA的地盘
// 4    int b(222)  BaseB的地盘8int c(3)Child 的地盘
struct Child : public BaseA, public BaseB {
    int c = 333;
};

int main() {
    Child p;
    BaseB sourceB;
    sourceB.b = 999; // 我们准备了一个新的 B,想把它拷进 p 里

    std::cout << "--- 拷贝前 ---" << std::endl;
    std::cout << "p.a = " << p.a << " (BaseA部分)" << std::endl;
    std::cout << "p.b = " << p.b << " (BaseB部分)" << std::endl;

    // --- 致命操作 ---
    // 程序员的意图:把 sourceB 的数据拷贝给 p
    // 程序员认为:p 既然继承了 BaseB,那我就直接拷过去
    std::memcpy(&p, &sourceB, sizeof(BaseB));

    std::cout << "\n--- 运行 memcpy(&p, &sourceB, ...) 后 ---" << std::endl;

    // 错位发生了!
    // 1. p.a 被改成了 999。因为 memcpy 从 p 的开头(BaseA的位置)开始写。
    // 2. p.b 依然是 222。因为它在内存后面,memcpy 根本没写到它。

    std::cout << "p.a = " << p.a << " (被错误覆盖了!)" << std::endl;
    std::cout << "p.b = " << p.b << " (完全没被拷进去!)" << std::endl;

    std::cin.get();

    return 0;
}