Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [FIXED] Access violation after program end  (Read 4638 times)

0 Members and 1 Guest are viewing this topic.

Ayasano

  • Newbie
  • *
  • Posts: 2
    • View Profile
[FIXED] Access violation after program end
« on: August 24, 2012, 06:10:55 am »
Edit: The fix for this is in my 2nd post.

So, I spent pretty much all day trying to fix this and am about ready to pull my hair out. My program runs fine right up until it exits main(), at which point it complains about "Unhandled exception at 0x006853cc in Tile Engine Tutorial.exe: 0xC0000005: Access violation reading location 0x02fec040." I'm using VC++ 2010 Express and SFML 2.0. The code is part of a tile engine for roguelike. (IN SPACE!)

//Include the tile engine
#include "Engine.h"

// basic file operations
#include <iostream>
#include <fstream>

using namespace std;

int main(int args, char* argc[])
{
        Engine* engine = new Engine(800, 600, 16);

        try
        {
                engine->Go();
        }
        catch(char* e)
        {
                ofstream errorLog;
                errorLog.open ("error.txt");
                errorLog << e;
                errorLog.close();
                return 0;
        }

        delete engine;
}

 

#ifndef _ENGINE_H
#define _ENGINE_H

// basic file operations
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>

#include <SFML\Graphics.hpp>
#include <SFML\System.hpp>
#include <SFML\Window.hpp>

//Memory leak detection with Visual Leak Detector
#include <vld.h>

#include "ImageManager.h"
#include "Tile.h"
#include "Camera.h"
#include "Level.h"
#include "Text.h"
#include "Player.h"
#include "Sound.h"

class Engine
{
private:
        //SFML Render Window
        sf::RenderWindow* window;
        sf::Window* windowMain;
        sf::Vector2i videoSize;

        //Camera
        Camera* camera;

        //Debug output for the camera
        TextOutput* cameraPos;
        std::string cameraPosX;
        std::string cameraPosY;
        std::string cameraPosString;

        //Debug output for the mouse
        TextOutput* mousePos;
        std::string mousePosX;
        std::string mousePosY;
        std::string mousePosString;

        ImageManager imageManager;

        //Window events.
        sf::Event evt;

        //Current Level
        Level* currentLevel;

        //Sound effects
        SoundEffect* collisionSound;

        //The global clock
        sf::Clock clock;
        sf::Time time1;

        //Tile Dimensions
        int tileSize;
       
        //The player
        Player* player;

        bool inShip;


        //Initializes the engine
        bool Init();                           
        //Main Game Loop
        void MainLoop();                       
        //Renders one frame
        void RenderFrame();
        //Processes user input
        void ProcessInput();
        //Updates all Engine internals
        void Update();

public:
        Engine(int w, int h, int tileSize);
        ~Engine();

        void Go();                                      //Starts the engine
};

#endif

#include "Engine.h"

#define DEBUG 0
#define AREA_SIZE 10

using namespace std;

Engine::Engine(int w, int h, int tileSize)
{
        videoSize = sf::Vector2i(w, h);
        this->tileSize = tileSize;
        imageManager.setTileSize(tileSize);
}

Engine::~Engine()
{

}

bool Engine::Init()
{
        //Set up the main window and associated debug output.
        window = new sf::RenderWindow(sf::VideoMode(videoSize.x, videoSize.y, 32), "RPG");
        if(!window)
                throw "Could not create window!";
        window->setFramerateLimit(60);
        mousePos = new TextOutput("swansea.ttf", 30);
        if(!mousePos)
                throw "Could not create mouse position text!";

        //Set up the camera and associated debug output.
        camera = new Camera(videoSize.x, videoSize.y, 1);
        if(!camera)
                throw "Could not create camera!";
        cameraPos = new TextOutput("swansea.ttf", 30);
        if(!cameraPos)
                throw "Could not create camera position text!";

        //Set up the player object, position the camera and listener and create any sound effects needed.
        player = new Player(4 * tileSize, 1 * tileSize, imageManager.LoadPlayer("player.png"));
        if(!player)
                throw "Could not create player!";
        collisionSound = new SoundEffect("knock.wav");
        if(!collisionSound)
                throw "Could not create sound!";
        sf::Listener::setPosition(player->playerPos.x, player->playerPos.y, -1);
        camera->MoveCenter(player->playerPos.x, player->playerPos.y);

        //Set up the level.
        currentLevel = new Level();
        if(!currentLevel)
                throw "Could not create level!";
        currentLevel->LoadLevel("shipList.xml", imageManager);
        inShip = false;


        return true;
}

void Engine::RenderFrame()
{      

        //Camera offsets
        int camOffsetX, camOffsetY;

        Tile* tile;

        window->setActive();
       
        //Get the tile bounds we need to draw
        sf::IntRect bounds = camera->GetTileBounds(tileSize);

        //Figure out how much to offset each tile
        camOffsetX = camera->GetTileOffset(tileSize).x;
        camOffsetY = camera->GetTileOffset(tileSize).y;

        //Draw the background so the map edges don't glitch
        sf::Texture backgroundTexture;
        backgroundTexture.loadFromFile("background.png");
        sf::Sprite backgroundSprite;
        backgroundSprite.setTexture(backgroundTexture);
        window->draw(backgroundSprite);

        //Loop through and draw each tile
        //We're keeping track of two variables in each loop. How many tiles
        //we've drawn (x and y), and which tile on the map we're drawing (tileX
        //and tileY)
        for(int y = 0, tileY = bounds.top; y < bounds.height; y++, tileY++)
        {
                for(int x = 0, tileX = bounds.left; x < bounds.width; x++, tileX++)
                {
                        //Get the tile we're drawing
                        tile = currentLevel->GetTile(tileX, tileY);

                        if(tile)
                        {
                                if(currentLevel->mapUnWalkable[tileX][tileY])
                                        tile->baseSprite.setColor(sf::Color::Red);
                                else
                                        tile->baseSprite.setColor(sf::Color::White);

                                tile->Draw((x * tileSize) - camOffsetX, (y * tileSize) - camOffsetY, window);
                        }
                }
        }
       

        if(DEBUG) //Display the camera and mouse co-ordinates in the bottom left corner of the screen
        {
                cameraPosX = static_cast<ostringstream*>( &(ostringstream() << camera->GetPosition().x) )->str();
                cameraPosY = static_cast<ostringstream*>( &(ostringstream() << camera->GetPosition().y) )->str();
                cameraPosString = "Camera Pos: " + cameraPosX + ", " + cameraPosY + ".";
                cameraPos->write(cameraPosString, window, sf::Vector2f(5, videoSize.y - cameraPos->text1.getCharacterSize() - 5));

                mousePosX = static_cast<ostringstream*>( &(ostringstream() << sf::Mouse::getPosition(*window).x) )->str();
                mousePosY = static_cast<ostringstream*>( &(ostringstream() << sf::Mouse::getPosition(*window).y) )->str();
                mousePosString = "Mouse Pos: " + mousePosX + ", " + mousePosY + ".";
                mousePos->write(mousePosString, window, sf::Vector2f(5, videoSize.y - (2 * mousePos->text1.getCharacterSize()) - 5));
        }

        //Draw the player in the center of the screen
        player->DrawPlayer(sf::Vector2f(videoSize.x/2, videoSize.y/2), window);

        window->display();
}

void Engine::ProcessInput()
{
        //Loop through all window events
        while(window->pollEvent(evt))
        {
                if(evt.type == sf::Event::Closed)
                {
                        window->close();
                        delete player;
                        delete collisionSound;
                        delete currentLevel;
                        delete camera;
                        delete cameraPos;
                        delete mousePos;
                }
        }
        //Check how long it was since we last took any input to avoid spam.
        time1 = clock.getElapsedTime();
        if(time1.asMilliseconds() > 500)
        {
                bool keyPressed = false;
               
                //Check to see if the player wants to move in a given direction, and whether they're at the map edge or next to a wall.
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) && player->playerPos.x > 0)
                {
                        if(!currentLevel->mapUnWalkable[(player->playerPos.x/tileSize) - 1][player->playerPos.y/tileSize])
                        {
                                player->playerPos.x -= tileSize;
                                keyPressed = true;
                        }
                        else
                                collisionSound->PlaySoundEffect();
                }
                else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && player->playerPos.x < AREA_SIZE)
                {
                        if(!currentLevel->mapUnWalkable[(player->playerPos.x/tileSize) + 1][player->playerPos.y/tileSize])
                        {
                                player->playerPos.x += tileSize;
                                keyPressed = true;
                        }
                        else
                                collisionSound->PlaySoundEffect();
                }
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && player->playerPos.y > 0)
                {
                        if(!currentLevel->mapUnWalkable[player->playerPos.x/tileSize][(player->playerPos.y/tileSize) - 1])
                        {
                                player->playerPos.y -= tileSize;
                                keyPressed = true;
                        }
                        else
                                collisionSound->PlaySoundEffect();
                }
                else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down) && player->playerPos.y < AREA_SIZE)
                {
                        if(!currentLevel->mapUnWalkable[player->playerPos.x/tileSize][(player->playerPos.y/tileSize) + 1])
                        {
                                player->playerPos.y += tileSize;
                                keyPressed = true;
                        }
                        else
                                collisionSound->PlaySoundEffect();
                }
                if(keyPressed)
                {
                        camera->MoveCenter(player->playerPos.x, player->playerPos.y);
                        sf::Listener::setPosition(player->playerPos.x, player->playerPos.y, -1);
                        clock.restart();
                }
        }
}

void Engine::Update()
{
        //Disabled for now
        if(inShip)
        {
                camera->Update();
        }
}

void Engine::MainLoop()
{
        //Loop until our window is closed
        while(window->isOpen())
        {
                ProcessInput();
                if(window->isOpen())
                {
                        Update();
                        RenderFrame();
                }
        }
        delete window;
}

void Engine::Go()
{
        if(!Init())
                throw "Could not initialize Engine";

        MainLoop();
}

#ifndef _SOUND_H
#define _SOUND_H

#include <SFML\Audio.hpp>

class SoundEffect
{
public:
        SoundEffect(std::string file);
        ~SoundEffect();
        void SoundEffect::PlaySoundEffect();

        sf::SoundBuffer buffer;
        sf::Sound sound;
};

#endif
 

#include "Sound.h"

SoundEffect::SoundEffect(std::string file)
{
        buffer.loadFromFile(file);
        sound.setBuffer(buffer);
}

SoundEffect::~SoundEffect()
{

}

void SoundEffect::PlaySoundEffect()
{
        sound.play();
}

Commenting out any reference to "sf::SoundBuffer buffer" or "sf::Sound sound" stops the access violation, so I'm pretty sure it's related to the sound module. The call stack also mentions openal32.dll last, and sfml-audio-d-2.dll right before it.

Apologies if my code sucks and/or is hard to read, it's a mix of a tutorial (From someone who uses new without delete) and my own code. (From someone who generally isn't very good)
« Last Edit: August 24, 2012, 07:12:31 pm by Ayasano »

ccleung6

  • Newbie
  • *
  • Posts: 22
    • View Profile
Re: Access violation after program end
« Reply #1 on: August 24, 2012, 07:02:17 am »
I also encountered this problem for SFML 2.0

Link statically may solve the problem, but I use MinGW 4.4 fail to static link SFML2.0.
SFML 1.6 can link statically and no such problem.

So I use 1.6, wait 2.0 to be officially released.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11032
    • View Profile
    • development blog
    • Email
Re: Access violation after program end
« Reply #2 on: August 24, 2012, 07:31:19 am »
Please reduce your code to a complete but minimal example the reproduces the error (e.g. a main function that holds a sf::Sound and crashes at the end).
What exacte version of SFML 2 are you using? What is the callstack when a crash happens?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Ayasano

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Access violation after program end
« Reply #3 on: August 24, 2012, 06:17:00 pm »
#include <SFML/Audio.hpp>

int main(int args, char* argc[])
{
        sf::Sound sound;
}

        openal32.dll!004653cc()        
        [Frames below may be incorrect and/or missing, no symbols loaded for openal32.dll]     
        openal32.dll!0042ca5c()        
        sfml-audio-d-2.dll!1000501a()  
        sfml-audio-d-2.dll!1002018d()  
        sfml-audio-d-2.dll!1001a564()  
        sfml-audio-d-2.dll!1001a770()  
        sfml-audio-d-2.dll!1001a631()  
        ntdll.dll!7c90118a()    
        ntdll.dll!7c9224ca()    
        ntdll.dll!7c910435()    
        ntdll.dll!7c91043e()    
        ntdll.dll!7c922678()    
        kernel32.dll!7c81caae()        
>       msvcr100d.dll!_free_base(void * pBlock=0x967c93d3)  Line 50 + 0x13 bytes        C
        8dffffff()     
 

Same crash with just that code, linked with sfml-main-d.lib, sfml-audio-d.lib

I'm using the 2.0 RC available from the download page. Incidentally, I tried compiling the latest snapshot, and it introduced more errors, but still included this one. (Specifically it crashed when trying to use << to write to a file, with unmodified code from the old version)

Edit: Never mind about the static linking issue, I just forgot to link against sfml-system-s-d.lib. However, that DOES fix the problem. No crash when statically linked.
« Last Edit: August 24, 2012, 07:09:17 pm by Ayasano »

 

anything