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.

C++:OpenCV:快速像素迭代

Laravel 5 - 找不到 MySQL 存储过程

cadence 16.6版本,在原理图中想添加room属性,编辑元件属性,在filter by里找不到cadence-allegro选项?

allegro 有找到cmlib.dll,因此这个应用程序未能启动