【问题标题】:(SDL Render Problem) C++ Exception Thrown: read access violation. THIS was nullptr(SDL 渲染问题)抛出 C++ 异常:读取访问冲突。这是 nullptr
【发布时间】:2019-09-09 06:41:32
【问题描述】:

每当我运行我的程序时,我都会在两行单独的代码上引发异常,如果我将其中一个注释掉,问题就会跳转到另一个,但它们都引用同一个变量。

GameScreenManager.cpp:

#pragma once
#include <SDL.h>
#include "Commons.h"
#include "GameScreenManager.h"
#include "GameScreenLevel1.h"
#include "GameScreen.h"

GameScreenManager::GameScreenManager(SDL_Renderer* renderer, SCREENS startScreen)
{
    SDL_Renderer* mRenderer;
    mRenderer = NULL;
    ChangeScreen(startScreen);
}

GameScreenManager::~GameScreenManager()
{
    mRenderer = NULL;
    delete mCurrentScreen;
    mCurrentScreen = NULL;
}

void GameScreenManager::Render()
{
    mCurrentScreen->Render();
}

void GameScreenManager::update(float deltaTime, SDL_Event e)
{
    mCurrentScreen->Update(deltaTime, e);
}

void GameScreenManager::ChangeScreen(SCREENS newScreen)
{
    //Clear up the old screen
    if (mCurrentScreen != NULL)
    {
        delete mCurrentScreen;
    }

    GameScreenLevel1* tempScreen;


    switch (newScreen)
    {
    case SCREEN_INTRO:
        break;
    case SCREEN_MENU:
        break;
    case SCREEN_LEVEL1:
        tempScreen = new GameScreenLevel1(mRenderer);
        mCurrentScreen = (GameScreen*)tempScreen;
        tempScreen = NULL;
        break;
    case SCREEN_LEVEL2:
        break;
    case SCREEN_GAMEOVER:
        break;
    case SCREEN_HIGHSCORES:
        break;
    default:
            break;
    }
}

GameScreenManager.h:

#pragma once
#ifndef _GAMESCREENMANAGER_H
#define _GAMESCREENMANAGER_H
#include <SDL.h>
#include "Commons.h"

class GameScreen;

class GameScreenManager
{
    private:
        SDL_Renderer*    mRenderer;
        GameScreen*      mCurrentScreen;

    public:
        GameScreenManager(SDL_Renderer* renderer, SCREENS startScreen);
        ~GameScreenManager();

        void Render();
        void update(float deltaTime, SDL_Event e);
        void ChangeScreen(SCREENS newScreen);
};

#endif //_GAMESCREENMANAGER_H

目前问题出现在第24行;

    mCurrentScreen->Render();

但是,如果我注释掉该行,那么它会出现在第 29 行:

    mCurrentScreen->Update(deltaTime, e);

"抛出未处理的异常:读取访问冲突。 this 为 nullptr。发生”

【问题讨论】:

  • 一个程序经常在距离错误实际存在数英里的地方崩溃。错误消息 this was nullptr 建议您找出为什么 thisnullptrmCurrentScreen = (GameScreen*)tempScreen; 错过了吗?

标签: c++ pointers exception null sdl


【解决方案1】:

显然,当您调用 Render() 或 update() 时,mCurrentScreen 字段为 NULL。通过检查 mCurrentScreen 是否为 NULL 来保护调用:

void GameScreenManager::Render()
{
    if (mCurrentScreen != NULL)
        mCurrentScreen->Render();
}

void GameScreenManager::update(float deltaTime, SDL_Event e)
{
    if (mCurrentScreen != NULL)
        mCurrentScreen->Update(deltaTime, e);
}

或确保在调用 Render() 或 Update() 之前设置了 mCurrentScreen。

【讨论】:

  • 我添加了 if 语句来检查 mCurrentScreen != NULL 是否为
  • 在 ChangeScreen() 中删除后将 mCurrentScreen 设置为 NULL
  • 如果mCurrentScreen 在使用前不能保证指向安全的东西,那么你注定要用if (mCurrentScreen != NULL) 包围每次使用。这是在玩 bug whack-a-mole,因为您会不断发现未设置的情况。并且未经测试。你最好确保mCurrentScreen 总是 指向安全的东西。
  • 我在删除 mCurrentScreen 后将 mCurrentScreen 设置为 NULL,但仍然出现异常。我什至完全删除了 if 语句,但仍然没有运气。
  • 如果在 if 语句中抛出异常,那么您的构建可能有问题 - 尝试清理/重建,删除所有中间文件等。您还应该在构造函数中将 mCurrentScreen 初始化为 NULL,但它不会帮助您在“if”s 上抛出异常。
【解决方案2】:

碰巧我实际上错过了设置 mCurrentScreen 的一行代码,并且 switch 语句没有正确通过,因此它没有触发。此外,我的任何 cpp 文件中的 mRenderer 变量都没有正确设置,因此每当我尝试使用它时都会返回“Invalid Renderer”。以下是工作代码,感谢大家的帮助,它引导我朝着正确的方向前进;

#pragma once
#include <SDL.h>
#include "Commons.h"
#include "GameScreenManager.h"
#include "GameScreenLevel1.h"
#include "GameScreen.h"

GameScreenManager::GameScreenManager(SDL_Renderer* renderer, SCREENS startScreen)
{
    mRenderer = renderer;
    GameScreen* mCurrentScreen = NULL;
    ChangeScreen(startScreen);
}

GameScreenManager::~GameScreenManager()
{
    mRenderer = NULL;
    delete mCurrentScreen;
    mCurrentScreen = NULL;
}

void GameScreenManager::Render()
{
    mCurrentScreen->Render();
}

void GameScreenManager::Update(float deltaTime, SDL_Event e)
{
    mCurrentScreen->Update(deltaTime, e);
}

void GameScreenManager::ChangeScreen(SCREENS newScreen)
{
    //Clear up the old screen
    if (mCurrentScreen != NULL)
    {
        delete mCurrentScreen;
    }

    GameScreenLevel1* tempScreen;

    switch (newScreen)
    {
    case SCREEN_INTRO:
        break;
    case SCREEN_MENU:
        break;
    case SCREEN_LEVEL1:
        tempScreen = new GameScreenLevel1(mRenderer);
        mCurrentScreen = (GameScreen*)tempScreen;
        tempScreen = NULL;
        break;
    case SCREEN_LEVEL2:
        break;
    case SCREEN_GAMEOVER:
        break;
    case SCREEN_HIGHSCORES:
        break;
    default:
        break;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-15
    • 2020-09-12
    • 2023-04-02
    • 2016-08-01
    • 2016-08-25
    • 2020-08-26
    • 2021-12-19
    • 1970-01-01
    相关资源
    最近更新 更多