结构访问冲突

Access violation on struct

我正在使用此代码获得 "Access violation reading location 0x0000000000000008.":

main.xcpp

Penguin::Game game;
game.memory = {};
game.memory.permanentSize = 1024*64;
game.memory.permanent = VirtualAlloc(0, game.memory.permanentSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
game.Start();

game.Start()

input = (Input *)memory.permanent;
*input = {}; // << Access violation reading location.

游戏结构

struct Game
{
    struct Memory
    {
        uint64  permanentSize;
        void    *permanent;
    };

    Memory memory;

    Input *input;

    void Start();
};

不过。如果我尝试:

int *i = (int *)memory.permanent;
*i = 10;

有效。

我做错了什么?

您在使用 VirtualAlloc 分配的未初始化内存上使用 Input class 的赋值运算符。这就是导致崩溃的原因。赋值运算符通常期望 Input 对象处于 有效状态 的左侧大小。您正在传递一块完全未初始化的原始内存,这会触发未定义的行为。

赋值运算符总是假定左侧包含旧数据,在一般情况下,在将新数据存储到它的位置之前必须以某种方式处理旧数据。但在您的情况下,左侧操作数包含垃圾。尝试使用 "normal" 方法销毁该垃圾会导致崩溃。您的调用堆栈显示您的 Input 中有一个 std::mapstd::map::clear() 是崩溃的原因。

换句话说,你所做的相当于这个

std::map<int, int> *p = (std::map<int, int> *) malloc(sizeof *p);
p->clear();

以上也会导致未定义的行为(很可能是崩溃),原因与它在您的代码中崩溃的原因完全相同。

不要尝试在原始内存(即非构造对象)上使用赋值运算符(以及任何其他重要的方法或操作)。

如果你想在 *input 上使用赋值运算符,你必须构造一个 首先是该内存中的有效 Input 对象。 Placement new 可以帮助你

input = new (memory.permanent) Input{};

现在 *input 是一个有效的、正确构造的类型 Input 的对象,它在赋值

的左侧(或任何一侧)也将表现正确
*input = {}; // OK

实际上,上面的 new 表达式也将执行您尝试使用赋值运算符执行的操作,这意味着不再需要该赋值。