#c #pointers #exception #null #sdl
#c #указатели #исключение #null #sdl
Вопрос:
Всякий раз, когда я запускаю свою программу, я получаю исключение, генерируемое для двух отдельных строк кода, если я закомментирую одну из них, проблема переходит к другой, но обе ссылаются на одну и ту же переменную.
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);
«Возникло необработанное исключение: нарушение доступа для чтения.
это был nullptr. произошло »
Комментарии:
1. Программа часто вылетает за много миль от того места, где на самом деле была ошибка. Сообщение об ошибке
this
было nullptr предполагает, что вы должны выяснить, почемуthis
это былоnullptr
. БылоmCurrentScreen = (GameScreen*)tempScreen;
пропущено?
Ответ №1:
По-видимому, поле mCurrentScreen имеет значение NULL при вызове Render() или update() . Либо защитите вызовы, проверив 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);
}
или убедитесь, что установлен mCurrentScreen перед вызовом Render() или Update() .
Комментарии:
1. Я добавил операторы if, чтобы проверить, является ли mCurrentScreen != NULL, и действуйте соответственно, однако я все равно получаю исключение, однако на этот раз для операторов if.
2. установите для mCurrentScreen значение NULL после удаления его в ChangeScreen()
3.Если
mCurrentScreen
не гарантируется, что перед его использованием будет указано на что-то безопасное, вы обречены окружать каждое использование сif (mCurrentScreen != NULL)
помощью . Это воспроизводит ошибку, потому что вы будете постоянно находить случаи, когда она не была установлена. и не проверялось. Вам гораздо лучше убедиться, что этоmCurrentScreen
всегда указывает на что-то безопасное.4. Я установил mCurrentScreen равным NULL после удаления mCurrentScreen и все равно получаю исключение. Я даже полностью удалил этот оператор if и все равно не повезло.
5. Если исключение генерируется в операторе if, вероятно, что-то не так с вашей сборкой — попробуйте очистить / перестроить, удалить все промежуточные файлы и т.д. Вы также должны инициализировать mCurrentScreen равным NULL в конструкторе, но это не поможет вам создавать исключения для «if».
Ответ №2:
Как оказалось, я фактически пропустил строку кода, которая устанавливала mCurrentScreen, и оператор switch проходил неправильно, поэтому он не срабатывал. Кроме того, переменная mRenderer не была настроена правильно ни в одном из моих файлов 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)
{
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;
}
}