C++ Allegro 5 - 找不到访问冲突的来源
Posted
技术标签:
【中文标题】C++ Allegro 5 - 找不到访问冲突的来源【英文标题】:C++ Allegro 5 - Can't find source of access violation 【发布时间】:2014-03-18 07:36:21 【问题描述】:我正在使用 Allegro 5 开发 C++ 游戏。从将所有代码放在 main.cpp 中的教程来看,它似乎运行良好。我已经将代码组织成类,但我现在在运行时遇到了这个错误:
“Face Chase Allegro5.exe 中 0x57052F4B (allegro-5.0.10-monolith-mt-debug.dll) 的第一次机会异常:0xC0000005:访问冲突读取位置 0x00000000。 Face Chase Allegro5.exe 中 0x57052F4B (allegro-5.0.10-monolith-mt-debug.dll) 处未处理的异常:0xC0000005:访问冲突读取位置 0x00000000。 程序“[6020] Face Chase Allegro5.exe”已退出,代码为 0 (0x0)。”
这是一些参考代码:
GameManager.h:
#pragma once
#include <allegro5\allegro.h>
#include "Singleton.h"
#include "SceneManager.h"
#include "InputManager.h"
typedef enum GAMESTATE TITLE, MAIN, GAME_OVER ;
class GameManager : public Singleton<GameManager>
private:
SceneManager* m_SceneManager; //manages the level and visual elements
InputManager* m_InputManager; //manages input variables
GAMESTATE m_gameState; //whether or not the game is at the title, main game, game over, etc.
ALLEGRO_EVENT_QUEUE* m_queue; //event queue, used for storing events to al_event
ALLEGRO_TIMER* m_timer; //timer for regulating FPS
bool m_gameEnd; //for keeping track of whether or not the program should close
bool m_redraw; //when certain conditions are met, the program will redraw the screen
protected:
Singleton<GameManager> *m_GameManager;
public:
GameManager();
~GameManager();
SceneManager* getSceneManager() return m_SceneManager;
GAMESTATE getGameState() return m_gameState;
ALLEGRO_EVENT_QUEUE* getEventQueue() return m_queue;
ALLEGRO_TIMER* getTimer() return m_timer;
bool getGameEnd() return m_gameEnd;
bool getRedraw() return m_redraw;
void setGameState(GAMESTATE newState) m_gameState = newState;
void setQueue(ALLEGRO_EVENT_QUEUE* queue) m_queue = queue;
void setTimer(ALLEGRO_TIMER* timer) m_timer = timer;
void setGameEnd(bool gameEnd) m_gameEnd = gameEnd;
void doControl(ALLEGRO_EVENT* ev);
;
GameManager.cpp:
#include "GameManager.h"
const int FPS = 60;
GameManager::GameManager() //This is where I encounter access violations at 0x00000000
m_SceneManager = new SceneManager;
m_InputManager = new InputManager;
m_gameState = TITLE; //when the program runs it starts at the title screen
m_queue = al_create_event_queue();
m_timer = al_create_timer(1.0 / FPS);
m_gameEnd = false;
m_redraw = false;
GameManager::~GameManager()
delete m_SceneManager;
m_SceneManager = NULL;
delete m_queue;
m_queue = NULL;
delete m_timer;
m_timer = NULL;
void GameManager::doControl(ALLEGRO_EVENT* ev)
if (ev->type == ALLEGRO_EVENT_MOUSE_AXES)
m_InputManager->setMousePos(ev->mouse.x, ev->mouse.y);
//code for tracking the mouse position; I plan to add button functionality and
//a custom cursor to the title screen in due time
if (ev->type == ALLEGRO_EVENT_DISPLAY_CLOSE ||
(ev->type == ALLEGRO_EVENT_KEY_DOWN && ev->keyboard.keycode == ALLEGRO_KEY_ESCAPE))
setGameEnd(true);
//instructs the program to close if the user clicks close or presses escape
switch (getGameState()) //gets the game state for evaluation
case TITLE: //event handling for the title screen
if((ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN && ev->mouse.button &1) ||
(ev->type == ALLEGRO_EVENT_KEY_DOWN && ev->keyboard.keycode == ALLEGRO_KEY_ENTER))
setGameState(MAIN);
break; //if the left button is clicked or enter is pressed, starts the main game
case MAIN: //event handling for main game
switch (ev->type)
case ALLEGRO_EVENT_KEY_DOWN:
switch (ev->keyboard.keycode) //handles movement of player character
case ALLEGRO_KEY_UP:
m_InputManager->setKeys(UP, true);
break;
case ALLEGRO_KEY_DOWN:
m_InputManager->setKeys(DOWN, true);
break;
case ALLEGRO_KEY_RIGHT:
m_InputManager->setKeys(RIGHT, true);
break;
case ALLEGRO_KEY_LEFT:
m_InputManager->setKeys(LEFT, true);
break;
case ALLEGRO_EVENT_KEY_UP:
switch (ev->keyboard.keycode)
case ALLEGRO_KEY_UP:
m_InputManager->setKeys(UP, false);
break;
case ALLEGRO_KEY_DOWN:
m_InputManager->setKeys(DOWN, false);
break;
case ALLEGRO_KEY_RIGHT:
m_InputManager->setKeys(RIGHT, false);
break;
case ALLEGRO_KEY_LEFT:
m_InputManager->setKeys(LEFT, false);
break;
bool collision;
bool* tempKeys[3];
for (int i = 0; i < 4; i++)
*tempKeys[i] = m_InputManager->getKey(i);
//updates keys array and player data
m_SceneManager->updateEntityCoords(tempKeys, collision);
场景管理器.h:
#pragma once
#include <iostream>
#include <allegro5\allegro.h>
#include <allegro5\allegro_audio.h>
#include <allegro5\allegro_acodec.h>
#include "InputManager.h"
#include "Entity.h"
class SceneManager
private:
ALLEGRO_DISPLAY* m_display; //main window display
ALLEGRO_BITMAP* m_background; //background during the main game
ALLEGRO_BITMAP* m_titleScreen; //title screen image
ALLEGRO_SAMPLE* m_titleMusic;
ALLEGRO_SAMPLE* m_bgMusic; //various sound assets
ALLEGRO_SAMPLE* m_soundDog;
ALLEGRO_SAMPLE* m_soundEat;
Entity* m_face; //player entity
Entity* m_poop;//poop entity
public:
SceneManager();
~SceneManager();
ALLEGRO_DISPLAY* getDisplay() return m_display;
ALLEGRO_BITMAP* getBackground() return m_background;
ALLEGRO_BITMAP* getTitleScreen() return m_titleScreen;
ALLEGRO_SAMPLE* getTitleMusic() return m_titleMusic;
ALLEGRO_SAMPLE* getBGM() return m_bgMusic;
ALLEGRO_SAMPLE* getSoundDog() return m_soundDog;
ALLEGRO_SAMPLE* getSoundEat() return m_soundEat;
Entity* getFace() return m_face;
Entity* getPoop() return m_poop;
void setDisplay(ALLEGRO_DISPLAY* display) m_display = display;
void setFace(Entity newFace) *m_face = newFace;
void setPoop(Entity newPoop) *m_poop = newPoop;
bool isCollision(Entity* entity1, Entity* entity2); //returns true if there is a collision
void updateEntityCoords(bool* keys[3], bool collision); //adjust player coordinates and moves the poop if it is collected
void UpdateHitbox(Entity* entity, EntityType type); //updates entity hitboxes
void BuildBackground(ALLEGRO_BITMAP* background); //builds the entire background from a single tile
void playTitleMusic()
al_play_sample(m_titleMusic, 255, 128, 1000, ALLEGRO_PLAYMODE_LOOP, NULL);
//title music loop when the program starts
void playMainSounds(); //main game sound loop
void updateDisplay(); //redraws the screen with updated data
;
SceneManager.cpp:
#include "SceneManager.h"
const int screenWidth = 640;
const int screenHeight = 480;
SceneManager::SceneManager()
m_display = al_create_display(screenWidth, screenHeight); //creates a 640 x 480 display
m_background = al_create_bitmap(640, 480);
m_titleScreen = al_load_bitmap("assets/title.bmp");
m_soundDog = al_load_sample("assets/dog.wav");
m_bgMusic = al_load_sample("assets/music.wav");
m_soundEat = al_load_sample("assets/eat.wav");
m_titleMusic = al_load_sample("assets/title.wav");
m_face = new Entity(FACE);
m_poop = new Entity(POOP);
SceneManager::~SceneManager()
delete m_display;
m_display = NULL;
delete m_background;
m_background = NULL;
delete m_titleScreen;
m_titleScreen = NULL;
delete m_titleMusic;
m_titleMusic = NULL;
delete m_bgMusic;
m_bgMusic = NULL;
delete m_soundDog;
m_soundDog = NULL;
delete m_soundEat;
m_soundEat = NULL;
delete m_face;
m_face = NULL;
delete m_poop;
m_poop = NULL;
bool SceneManager::isCollision(Entity* entity1, Entity* entity2)
if (entity1->getHitbox()->x < entity2->getHitbox()->w &&
entity1->getHitbox()->y < entity2->getHitbox()->h &&
entity1->getHitbox()->w > entity2->getHitbox()->x &&
entity1->getHitbox()->h > entity2->getHitbox()->y)
return true;
else
return false;
void SceneManager::updateEntityCoords(bool* keys[3], bool collision)
getFace()->setY(getFace()->getY() - (*keys[UP] * 7));
getFace()->setY(getFace()->getY() + (*keys[DOWN] * 7));
getFace()->setX(getFace()->getX() - (*keys[LEFT] * 7));
getFace()->setX(getFace()->getX() + (*keys[RIGHT] * 7));
if (collision) //moves poop in case of collision
getFace()->setScore(getFace()->getScore() + 1);
getPoop()->setX(rand() % 448);
getPoop()->setY(rand() % 608);
void SceneManager::UpdateHitbox(Entity* entity, EntityType type)
switch (type)
case FACE:
entity->setHitbox(entity->getX(),
entity->getY(),
entity->getX() + 64,
entity->getY() + 64);
break;
case POOP:
entity->setHitbox(entity->getX(),
entity->getY(),
entity->getX() + 32,
entity->getY() + 32);
break;
void SceneManager::BuildBackground(ALLEGRO_BITMAP* background)
ALLEGRO_BITMAP *bgtile = al_load_bitmap("assets\bg.bmp");
al_set_target_bitmap(background);
//creates a struct of type ALLEGRO_BITMAP and sets Allegro's draw
//target to it
for(int i = 0; i <= 640; i++)
if(i % 32 == 0)
for(int j = 0; j <= 480; j++)
if(j % 32 == 0)
al_draw_bitmap(bgtile, 0, 0, NULL);
std::cout << "Placed tile at " << i << ", " << j << "\n";
al_destroy_bitmap(bgtile); //destroys bgtile since the background is generated
//and bgtile will no longer be needed
void SceneManager::playMainSounds()
al_stop_samples(); //stops looping title music and plays main game music
al_play_sample(m_soundDog, 255, 128, 1000, ALLEGRO_PLAYMODE_ONCE, NULL);
al_play_sample(m_bgMusic, 255, 128, 1000, ALLEGRO_PLAYMODE_LOOP, NULL);
void SceneManager::updateDisplay()
al_set_target_backbuffer(getDisplay()); //sets target back to display's back buffer and draws the objects to it
al_draw_bitmap(m_background, 0, 0, NULL);
al_draw_bitmap(m_face->getSprite(), m_face->getX(), m_face->getY(), NULL);
al_draw_bitmap(m_poop->getSprite(), m_poop->getX(), m_poop->getY(), NULL);
main.cpp:
#include <allegro5\allegro.h>
#include <allegro5\allegro_font.h>
#include <allegro5\allegro_ttf.h>
#include <allegro5\allegro_primitives.h>
#include "GameManager.h"
int main(void)
GameManager* manager = GameManager::getInstance();
//create game manager
if (!al_init()) //returns a value of -1 if
return -1; //Allegro does not initialize properly
if (!manager->getSceneManager()->getDisplay()) //returns -1 if the display window is
return -1; //not initialized properly
al_init_primitives_addon(); //allows for drawing basic shapes via functions
al_init_font_addon(); //allows for drawing text to the screen
al_init_ttf_addon(); //allows for drawing true type fonts
al_install_keyboard(); //gets input from keyboard
al_install_mouse(); //gets input from mouse
//registers display, keyboard, mouse, and timer as sources of events
al_register_event_source(manager->getEventQueue(), al_get_display_event_source(manager->getSceneManager()->getDisplay()));
al_register_event_source(manager->getEventQueue(), al_get_keyboard_event_source());
al_register_event_source(manager->getEventQueue(), al_get_mouse_event_source());
al_register_event_source(manager->getEventQueue(), al_get_timer_event_source(manager->getTimer()));
//starts timer for regulating FPS
al_start_timer(manager->getTimer());
//start of main loop
while (!manager->getGameEnd())
ALLEGRO_EVENT al_event;
al_wait_for_event(manager->getEventQueue(), &al_event);
//creates an event that catches things that happen such as key presses and mouse clicks
//and then instructs the program to wait for one of these things to happen and store it
//to al_event
manager->getSceneManager()->updateDisplay(); //update window display
manager->doControl(&al_event); //handles input and updates data accordingly
Visual Studio 告诉我问题出在 SceneManager.cpp 的构造函数中。首先它不喜欢 m_display。如果我注释掉那条线,它不喜欢 m_background。我将其注释掉,它不喜欢 m_titleScreen 并且对于这些更改中的每一个都给我一个相同的错误。所以我完全不知道这里的问题是什么。有什么想法吗?
【问题讨论】:
缺少一些代码,例如 GameManager::getInstance()。您可以在没有 new 的情况下将 GameManager 实例化为 main 中的变量。 - Visual Studio 如何表达它的厌恶? 我只是添加了一些参考代码;这不是整个程序。如果您真的需要,我将使用其余代码更新我的帖子,但这与我遇到的问题完全无关。 getInstance() 属于从中派生 GameManager 的 Singleton 模板。我从 Visual Studio 收到的错误在我帖子的第一部分。 由于没有其他人试图提供帮助,我只能建议像 0x57052F4B 或 0xC0000005 这样的地址可以通过称为“链接器映射”的东西来解释,显示每个对象模块在 .exe 文件中的加载位置.这可能会揭示错误的位置。除此之外:检查应该返回指针的任何内容(并且您有很多这样的调用)不会返回 NULL 指针。永远不要相信一些代码应该返回一个指向一个对象的指针,它总是返回一个有效的,即非 NULL 值。 到目前为止,我已经能够将其归结为程序在使用 al_create_display() 和 al_load_bitmap() 时简单地崩溃。不过,为什么它给我 NULL 指针超出了我的理解。希望有人能提供帮助,但在那之前我会继续努力。 【参考方案1】: GameManager* manager = GameManager::getInstance();
//create game manager
if (!al_init()) //returns a value of -1 if
return -1; //Allegro does not initialize properly
这只是猜测,但这看起来像是危险的代码。 al_init()
必须在(几乎)所有其他 Allegro 方法之前调用。
确保在调用其必备的 init 方法之前没有调用任何 Allegro 方法。
【讨论】:
以上是关于C++ Allegro 5 - 找不到访问冲突的来源的主要内容,如果未能解决你的问题,请参考以下文章
使用 g++ 编译器 (Ubuntu) 将 Allegro 库链接到 C++ 应用程序
allegro16.3版本的,如何加固定孔呢,找不到 layout__pins.
cadence 16.6版本,在原理图中想添加room属性,编辑元件属性,在filter by里找不到cadence-allegro选项?