使用SFML开发Asteroids程序触发0xC0000005访问违例求助
解决SFML Asteroids程序发射鱼雷时的崩溃问题
嘿,我看了你的代码和错误提示,这个崩溃问题其实是几个常见的指针使用错误导致的,咱们一步步来捋清楚:
首先,你遇到的0xC0000005: Access violation reading location 0x00000018错误,本质是对空指针(NULL)调用了成员函数——当你尝试访问空指针指向的对象的内部成员时,就会触发这个访问违例(0x18是成员在对象里的内存偏移)。
核心错误点1:完全错误的空指针检查逻辑
你代码里所有检查指针有效性的地方都写错了:
// 错误的写法:检查的是数组元素的地址,永远不会为NULL if (&photons[index] != NULL) { ... } if (&asteroids[index] != NULL) { ... }
photons是一个指针数组,&photons[index]是这个数组中第index个元素的存储地址(也就是数组本身的内存位置),这个地址永远不可能是NULL。你真正需要检查的是数组里的指针本身是否指向有效对象,应该写成:
// 正确的写法:检查指针本身是否为空 if (photons[index] != NULL) { ... } if (asteroids[index] != NULL) { ... }
原来的错误逻辑会导致程序不管指针是不是空,都去调用updatePosition()或draw(),一旦指针是空的,就会触发崩溃。
核心错误点2:发射鱼雷的逻辑不合理
你现在的按键事件里,每次按空格都会遍历整个MAX_PHOTONS数组,强制给每个位置都new一个新的鱼雷:
for (int index = 0; index < MAX_PHOTONS; index++) { photons[index] = new SpaceObject(...) // 这里还少了分号! ... }
这会导致两个问题:
- 每次按空格都会覆盖所有已存在的鱼雷,还会造成严重的内存泄漏(旧的鱼雷对象没被delete就被覆盖了);
- 如果你的
photons数组初始化时没有被设为全NULL,里面的野指针会直接导致崩溃。
正确的逻辑应该是找到第一个空闲的(指针为NULL)位置,只发射一枚鱼雷,同时补上遗漏的分号:
//check for keypress if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space) { // 遍历数组找第一个空闲位置 for (int index = 0; index < MAX_PHOTONS; index++) { if (photons[index] == NULL) { photons[index] = new SpaceObject(PHOTON_TORPEDO, PHOTON_RADIUS, ship->getLocation(), ship->getVelocity(), ship->getAngle()); photons[index]->applyThrust(PHOTON_SPEED); std::cout << "LAUNCHING TORPEDO\n"; break; // 只发射一枚,退出循环 } } }
额外注意:初始化指针数组
最后,要确保你的photons数组在定义时被初始化为全NULL,否则数组里的指针会是随机的野指针,同样会导致崩溃:
// 初始化所有指针为NULL,确保一开始都是空闲状态 SpaceObject* photons[MAX_PHOTONS] = {NULL};
把这些修改之后,你的崩溃问题应该就能解决了。另外记得在鱼雷消失后(比如飞出屏幕或击中 asteroid),要delete对应的指针并把它设回NULL,避免内存泄漏和无效指针访问。
内容的提问来源于stack exchange,提问作者tinyJman
相关产品推荐
相关产品推荐

