我已将这些函数添加到我的代码中,但我的程序开始崩溃并随机显示 SDL_2.exe 中 0x6C7B52E7 (SDL2.dll) 处未处理的异常:0xC0000005:访问冲突写入位置 0xFF00000C。调试器显示完全随机的代码片段,这些代码以前运行良好,这让我想到,这些新函数会弄乱内存。
void ObstacleSet::move()
{
Obstacles.push_back(Obstacle(mScreenWidth, mScreenHeight / 6 + 100, 10, 10, Coin, -29, 0));
Obstacles.push_back(Obstacle(mScreenWidth, mScreenHeight / 6 + 120, 10, 10, Coin, -29, 0));
Obstacles.push_back(Obstacle(mScreenWidth, mScreenHeight / 6 + 140, 10, 10, Coin, -29, 0));
Obstacles.push_back(Obstacle(mScreenWidth, mScreenHeight / 6 + 160, 10, 10, Coin, -29, 0));
Obstacles.push_back(Obstacle(mScreenWidth, mScreenHeight / 6 + 180, 10, 10, Coin, -29, 0));
for (auto &i : Obstacles)
{
i.move();
}
}
void ObstacleSet::outCheck(unsigned int &score)
{
for (unsigned int i = 0; i < getSize();)
{
if (getVelX(i) < 0 && (getX(i) + getW(i) <= 0))
{
eraseObstacle(i);
score++;
}
else if (getVelX(i) > 0 && (getX(i) >= mScreenWidth))
{
eraseObstacle(i);
score++;
}
else if (getVelY(i) > 0 && (getY(i) + getH(i) >= mScreenHeight))
{
eraseObstacle(i);
score++;
}
else if (getVelY(i) < 0 && (getY(i) <= 0))
{
eraseObstacle(i);
score++;
}
else
{
++i;
}
}
}
显然,我有一些内存泄漏,或者以某种方式出现了悬空指针,但我就是看不到哪里。也许我有一个错误的构造函数或其他东西。
ObstacleSet 是一个类,它将所有障碍物保存在一个列表中。
#ifndef MOBSTSET_H
#define MOBSTSET_H
#include <SDL.h>
#include <cstdlib>
#include "my_OBSTACLES.h"
#include <list>
class ObstacleSet
{
public:
ObstacleSet(int ScreenWidth, int ScreenHeight);
int mScreenWidth;
int mScreenHeight;
void clear();
//Function, that moves the set depending on current time
void move();
//Render set on screen
void render(SDL_Renderer *Renderer);
unsigned int getSize();
float getX(int);
float getY(int);
int getW(int);
int getH(int);
float getVelX(int);
float getVelY(int);
Type GetType(int);
void eraseObstacle(int);
void outCheck(unsigned int &score);
std::list<Obstacle>::iterator getEnd();
private:
//Vector to hold all obstacles
std::list <Obstacle> Obstacles;
};
#endif
这些一个接一个出现在我的主游戏循环中
障碍类标题
#ifndef MYOBSTACLE_H
#define MYOBSTACLE_H
#include <SDL.h>
#include <cmath>
#include <vector>
#include <cstdlib>
enum Type
{
Wall,
Coin
};
class Obstacle
{
public:
Obstacle();
//Initializer with parameters
Obstacle(float x, float y, int w, int h, Type type, float VelocityX = 0, float VelocityY = 0);
float VelocityX = 0;
float VelocityY = 0;
float xPos;
float yPos;
int mWidth;
int mHeight;
//Type of obstacle
Type OBSType;
//Render obstacle on screen
void render(SDL_Renderer *Renderer);
//Move obstacle
void move();
int mRed = 200;
int mGreen = 200;
int mBlue = 20;
bool color_up = false;
};
#endif
这些是我的 Obstacle 构造函数
Obstacle::Obstacle() : xPos(10), yPos(10), mWidth(10), mHeight(10), VelocityX(0), VelocityY(0), OBSType(Coin), mRed(200), mGreen(200), mBlue(20), color_up(false)
{
printf("Obstacle created!");
}
Obstacle::Obstacle(float x, float y, int w, int h, Type type, float velocityX, float velocityY) : xPos(x), yPos(y), mWidth(w), mHeight(h), VelocityX(velocityX), VelocityY(velocityY), OBSType(type), mRed(200), mGreen(200), mBlue(20), color_up(false)
{
}
下面是ObstacleSet的一些函数
void ObstacleSet::eraseObstacle(int number)
{
unsigned N = number;
std::list<Obstacle>::iterator i = Obstacles.begin();
if (Obstacles.size() > N)
{
std::advance(i, N);
}
Obstacles.erase(i);
}
unsigned int ObstacleSet::getSize()
{
return Obstacles.size();
}
float ObstacleSet::getX(int number)
{
unsigned N = number;
std::list<Obstacle>::iterator i = Obstacles.begin();
if (Obstacles.size() > N)
{
std::advance(i, N);
}
return i->xPos;
}
std::list<Obstacle>::iterator ObstacleSet::getEnd()
{
return Obstacles.end();
}
SDL初始化代码
bool init()
{
//Initialization flag
bool success = true;
//Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0)
{
printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
//Set texture filtering to linear
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
{
printf("Warning: Linear texture filtering not enabled!");
}
//Initialize SDL_mixer
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
{
printf("SDL_mixer could not initialize! SDL_mixer Error: %s\n", Mix_GetError());
success = false;
}
//Check for joysticks
if (SDL_NumJoysticks() < 1)
{
printf("Warning: No joysticks connected!\n");
}
else
{
//Load joystick
gGameController = SDL_JoystickOpen(0);
if (gGameController == NULL)
{
printf("Warning: Unable to open game controller! SDL Error: %s\n", SDL_GetError());
}
}
//Create window
gWindow = SDL_CreateWindow("Jello demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (gWindow == NULL)
{
printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Create vsynced renderer for window
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (gRenderer == NULL)
{
printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
//Initialize renderer color
SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))
{
printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError());
success = false;
}
//Initialize SDL_ttf
if (TTF_Init() == -1)
{
printf("SSDL_ttf could not initialize! SDL_ttf Error: %s\n", TTF_GetError());
success = false;
}
}
return success;
}
也许我有内存泄漏或悬挂指针,但我找不到错误在哪里。如果有人能找到我错的地方,我将非常高兴。如果您需要任何其他代码片段,请写信给我
最佳答案
除非你在某处有一个不变量来保证 ObstacleSet 永远不会调用空 Obstacles 列表上的任何东西,否则就有潜在的问题。
此代码在空列表上有未定义的行为
float ObstacleSet::getX(int number)
{
unsigned N = number;
std::list<Obstacle>::iterator i = Obstacles.begin();
if (Obstacles.size() > N)
{
std::advance(i, N);
}
return i->xPos;
}
试图修复它
float ObstacleSet::getX(int number)
{
unsigned N = number;
std::list<Obstacle>::iterator i = Obstacles.begin();
if (Obstacles.size() > N)
{
std::advance(i, N);
}
if (i != Obstacles.end())
return i->xPos;
// handle empty
return ERRORPOS; // or throw or assert or ...
}
与访问列表的所有其他函数相同。
关于C++可能的构造函数错误违规写入位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29809813/