C++可能的构造函数错误违规写入位置

标签 c++ access-violation sdl-2 push-back

我已将这些函数添加到我的代码中,但我的程序开始崩溃并随机显示 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/

相关文章:

c++ - 外部 "C"DLL : Debug is OK, 发布抛出错误 C2059

c++ - 名称冲突时局部变量和类属性的优先级

c++ - ORM 事务提交上的 Wt Segfault

audio - 有没有办法使用一些 SDL_Mixer 的功能来加速音频 .wav 文件?

c++ - 解释 C++/SDL2 程序的 valgrind 输出

c++ - QT中的程序终止回调?

c++ - 如何解释此调用堆栈信息

c - 第一次机会异常 : KernelBase. dll

c# - 如何解释此堆栈跟踪

c++ - 正在解决错误 LNK2019;未解析的外部符号