这是我制作的简单游戏的一段代码。此例程检查阵列中的每个项目符号或敌人,如果它们已经超过屏幕,则将其从阵列中删除。 (此代码使用SDL2,但我认为不重要。)
void cleanEnemies(Enemy* a[], int* s)
{
Enemy* e;
for (int i = 0; i < *s; i++)
{
e = a[i];
if (e->getX() < -75)
{
e->~Enemy();
e = NULL;
for (int j = i; j < *s; j++)
{
a[j] = a[j + 1];
}
(*s)--;
}
}
printf("Enemy count: %i\n", *s);
}
void cleanMissiles(HomingMissile* a[], int* s)
{
HomingMissile* m;
for (int i = 0; i < *s; i++)
{
m = a[i];
if (m->getX() < -75)
{
m->~HomingMissile();
m = NULL;
for (int j = i; j < *s; j++)
{
a[j] = a[j + 1];
}
(*s)--;
}
}
printf("Missile count: %i\n", *s);
}
运行程序会生成指向无效内存位置的指针。谁能告诉我我做错了什么?感谢。
答案 0 :(得分:1)
问题的原因是(我认为)内部for
循环超出了数组的范围。
void cleanMissiles(HomingMissile* a[], int* s)
{
HomingMissile* m;
// Suggests there are *s entries, so last entry is (*s)-1
for (int i = 0; i < *s; i++)
{
m = a[i];
if (m->getX() < -75)
{
m->~HomingMissile();
m = NULL;
// Last value of j is (*s) - 1
for (int j = i; j < *s; j++)
{
// Here it copies into a[(*s)] -1 from [a(*s)] which is invalid
a[j] = a[j + 1];
}
(*s)--;
}
}
printf("Missile count: %i\n", *s);
}
固定版本如下(依赖于如果在输入时不满足循环条件,for
循环将永远不会执行的事实):
void cleanMissiles(HomingMissile* a[], int* s)
{
HomingMissile* m;
for (int i = 0; i < *s; i++)
{
m = a[i];
if (m->getX() < -75)
{
m->~HomingMissile();
m = NULL;
for (int j = i + 1; j < *s; j++)
{
a[j - 1] = a[j];
}
(*s)--;
}
}
printf("Missile count: %i\n", *s);
}
但不是解决这个问题,请让您的生活更轻松,切换到std::vector
或更好std::list
,并致电delete
(假设您已分配new
)而不是直接调用析构函数。
答案 1 :(得分:0)
使用std::vector<std::unique_ptr<T>>
,它会变成像:
void cleanEnemies(std::vector<std::unique_ptr<Enemy>>& enemies)
{
auto it = std::remove_if(enemies.begin(), enemies.end(),
[](const auto& enemy) {
return enemy->getX() < -75;
});
enemies.erase(it, enemies.end());
std::cout << "Enemy count: " << enemies.size() << std::endl;
}
您甚至可以制作模板来处理Enemy
和HomingMissile
template <typename T>
void cleanObjects(std::vector<std::unique_ptr<T>>& objects, const std::string& objectName)
{
auto it = std::remove_if(objects.begin(), objects.end(),
[](const auto& object) {
return object->getX() < -75;
});
objects.erase(it, objects.end());
std::cout << objectName << " count: " << objects.size() << std::endl;
}
然后cleanEnemies
/ cleanMissiles
可以改写为:
void cleanEnemies(std::vector<std::unique_ptr<Enemy>>& enemies)
{
cleanObjects(enemies, "Enemy");
}
void cleanMissiles(std::vector<std::unique_ptr<HomingMissile>>& missiles)
{
cleanObjects(missiles, "Missile");
}