29

我正在开发的一款太空侵略者游戏遇到了一个非常奇怪的问题。基本上我得到一个访问冲突错误:

SpaceInvaders.exe 中 0x5edad442 (msvcr100d.dll) 处的未处理异常:0xC0000005:访问冲突读取位置 0x00000000。

当我包含下面的代码时。调试时,Visual Studio 将我带到“strcmp.asm”。请注意,我没有在我的任何代码中使用 strcmp() 。代码有什么问题,还是超出我所包含的范围的问题?谢谢你的帮助

const char* invarray[] = {"invader0.png", "invader1.png", "invader2.png", "invader3.png", "invader4.png"}; 
int i=0;
//Creates 55 invaders
for (int y=0; y<250; y+=50){
    for (int x=0; x<550;x+=50){
        Invader inv(invarray[y/50], x+50, y+550, 15, 15, 1, false, 250);
        invaders[i] = inv;
    }
}

入侵者构造函数:

Invader::Invader(const char *pic, int x, int y, int w, int h, bool dir, bool des, int point) : MovingObject(pic, x, y, w, h) , direction(dir), destroyed(des), b(0), points(point){};

移动对象构造函数

MovingObject::MovingObject(const char *pic, int x, int y, int w, int h):picture(pic), positionX(x), positionY(y), width(w), height(h) {};
4

3 回答 3

36

访问冲突读取位置 0x00000000 ”意味着您正在取消引用尚未初始化的指针,因此具有垃圾值。这些垃圾值可以是任何东西,但通常它恰好是0,因此您尝试从内存地址中读取0x0,操作系统会检测并阻止您这样做。

检查并确保阵列invaders[]是您认为应该的阵列。

此外,您似乎i永远不会更新 - 这意味着您在每次循环迭代时都将相同的Invader对象放置在位置。0invaders[]

于 2012-05-07T08:35:22.750 回答
18

这条线看起来很可疑:

invaders[i] = inv;

你永远不会增加i,所以你一直分配给invaders[0]. 如果这只是您在将代码简化为示例时所犯的错误,请检查您i在实际代码中的计算方式;你可能超过invaders.

如果正如您的评论所暗示的那样,您正在创建 55 invaders,然后检查invaders是否已正确初始化以处理此数字。

于 2012-05-07T08:37:52.587 回答
8

正如其他评论中所解释的,这里的问题是指针在没有正确初始化的情况下被取消引用。Linux 等操作系统将最低地址(例如前 32MB:0x00_0000 -0x200_0000)保留在进程的虚拟地址空间之外。这样做是因为取消引用归零的非初始化指针是一个常见的错误,就像在这种情况下一样。因此,当这种类型的错误发生时,不是实际读取恰好位于地址 0x0 的随机变量(但不是指针如果正确初始化后的内存地址),而是从外部的内存地址读取进程的虚拟地址空间。这会导致页面错误,从而导致分段错误,并向进程发送信号以将其杀死。这就是您收到访问冲突错误的原因。

于 2018-03-01T16:19:42.140 回答