【问题标题】:Access violation on struct结构上的访问冲突
【发布时间】:2015-08-08 18:03:14
【问题描述】:

我收到“访问冲突读取位置 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;

有效。

我做错了什么?

【问题讨论】:

  • 你有一个调试器,学习如何使用它!

标签: c++ pointers memory struct access-violation


【解决方案1】:

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

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

也就是说,你所做的就相当于这个

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

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

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

如果你想在*input 上使用赋值运算符,你必须构造一个 首先在该内存中有效的Input 对象。新的展示位置可以帮到您

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

现在*inputInput 类型的有效、正确构造的对象,它在赋值的左侧(或任何一侧)也将正常运行

*input = {}; // OK

实际上,上面的 new-expression 也将执行您尝试对赋值运算符执行的操作,这意味着不再需要该赋值。

【讨论】:

  • 效果很好。非常感谢您提供这些信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多