Ownership of my new Unique_ptrs? - c++

As per suggestion at a job interview I had recently, I was advised to research into the unique_ptr functionality of C++11, as a means of automated garbage collection. So I'm using an older project and replacing my raw pointers to objects created with the 'new' keyword, with unique_ptrs. However I think I have arrived at an issue of ownership.
In my mainclass.cpp (posted below) please turn your attention to the init function and the 3 unique_ptrs to new-instantiated objects I have created. Named "bg","bg2", and "theGrid".
(The commented out declarations below them are how they used to be done, and switching back to this method, the program runs just fine.)
However, using the unique_ptrs, the line in the function void display():
theGrid->doGridCalculations();//MODEL
generates an access violation. This is also the first time in the sequence that any of the pointed objects are dereferenced, which leads me to believe that ownership of the unique_ptr is already lost somewhere. However, the unique_ptrs themselves are never passed into another function or container, and remain in the scope of the mainclass.cpp and therefore I've seen no opportunity to use std::move(theGrid) in order to transfer ownership to where it needs to be.
Mainclass.cpp:
#include <stdio.h>
#include <GL/glut.h>
#include <math.h>
#include "Block.h"
#include "dStructs.h"
#include "Grid.h"
#include "Texture.h"
#include "freetype.h"
#include <Windows.h>
//////////////////////////////////////////////////////
///Declare a couple of textures - for the background
//////////////////////////////////////////
Texture* bg;
Texture* bg2;
//and theGrid
Grid* theGrid;
/////////////////////////////////////////////////
///Declare our font
/////////////////////////////////////////////////
freetype::font_data scoreFont;
/////////////////////////////////////////////////////////
//Initialize the variables
///////////////////////////////////////////////////////
typedef dStructs::point point;
const int XSize = 755, YSize = 600;
point offset = {333,145};
point mousePos = {0,0};
void init(void)
{
//printf("\n......Hello Guy. \n....\nInitilising");
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,XSize,0,YSize);
//////////////////////////
//initialise the fonts
/////////////////////////
try{
scoreFont.init("Visitor TT2 BRK Regular.ttf", 20);
} catch (std::exception &e) {
MessageBox(NULL, e.what(), "EXCEPTION CAUGHT", MB_OK | MB_ICONINFORMATION);
}
///////////////////////////////////////////////////////////////
///bg new MEMORY MANAGED EDITION
//////////////////////////////////////////////////////////////////
unique_ptr<Texture> bg(new Texture(1024,1024,"BackGround.png"));
unique_ptr<Texture> bg2(new Texture(1024,1024,"BackGround2.png"));
unique_ptr<Grid> theGrid(new Grid(offset));
/////////////////////////////////////////////////
/// Old bad-memory-management style of pointed objects
/////////////////////////////////////////////////
//bg = new Texture(1024,1024,"BackGround.png");
//bg2 = new Texture(1024,1024,"BackGround2.png");
//theGrid = new Grid(offset);
glClearColor(0,0.4,0.7,1);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//activate the alpha blending functionality
glEnable(GL_BLEND);
glLineWidth(2); // Width of the drawing line
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
//printf("\nInitialisation Complete");
}
void myPassiveMouse(int x, int y)
{
//Stupid OGL coordinate system
y = YSize - y;
mousePos.x = x;
mousePos.y = y;
printf("\nthe mouse coordinates are (%f,%f)",mousePos.x, mousePos.y);
}
void displayGameplayHUD()
{
///////////////////////////////
//SCORE
//////////////////////////////
glColor4f(0.7f,0.0f,0.0f,7.0f);//set the colour of the text
freetype::print(scoreFont, 100,400,"SCORE: ");
glColor4f(1.0f,1.0f,1.0f,1.0f);//Default texture colour. Makes text white, and all other texture's as theyre meant to be.
}
//////////////////////////////////////////////////////
void display()
{
////printf("\nBeginning Display");
glClear(GL_COLOR_BUFFER_BIT);//clear the colour buffer
glPushMatrix();
theGrid->doGridCalculations();//MODEL
point bgLoc = {XSize/2,YSize/2};
point bgSize = {XSize,YSize};
bg2->draw(bgLoc,bgSize);
theGrid->drawGrid();//DISPLAY
bg->draw(bgLoc,bgSize);
if(theGrid->gridState == Grid::STATIC)
{
theGrid->hoverOverBlocks(mousePos);//CONTROLLER
}
displayGameplayHUD();
glPopMatrix();
glFlush(); // Finish the drawing
glutSwapBuffers();
////printf("\nFresh Display Loaded");
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv); // GLUT Initialization
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE); // Initializing the Display mode
glutInitWindowSize(755,600); // Define the window size
glutCreateWindow("Gem Miners"); // Create the window, with caption.
init(); // All OpenGL initialization
//-- Callback functions ---------------------
glutDisplayFunc(display);
//glutKeyboardFunc(mykey);
//glutSpecialFunc(processSpecialKeys);
//glutSpecialUpFunc(processSpecialUpKeys);
glutMouseFunc(mymouse);
glutPassiveMotionFunc(myPassiveMouse);
glutMainLoop(); // Loop waiting for event
}
I think the ownership needs to be transferred at some point, but I don't know where.
Thanks in advance,
Guy

These are global raw pointers:
Texture* bg;
Texture* bg2;
//and theGrid
Grid* theGrid;
These are completely unrelated unique_ptrs, local to the init function.
unique_ptr<Texture> bg(new Texture(1024,1024,"BackGround.png"));
unique_ptr<Texture> bg2(new Texture(1024,1024,"BackGround2.png"));
unique_ptr<Grid> theGrid(new Grid(offset));
When the unique_ptrs go out of scope, they are destroyed. The objects that they point to are also destroyed, because that is what unique_ptr does in its destructor. At no point in that process were the global raw pointers involved with the debacle. They were hidden by the local unique_ptrs of the same name.
You should change your global raw pointers to unique_ptrs. Then you can set them (don't re-declare them) in the init function like this:
bg.reset(new Texture(1024,1024,"BackGround.png"));
bg2.reset(new Texture(1024,1024,"BackGround2.png"));
theGrid.reset(new Grid(offset));

The unique pointers that you create in your init function do not modify the pointers declared at file scope, the ones at file scope are default-initialised to 0 or nullptr (I'm not that well versed at C++11 so I'm not sure which).
What you're doing in the init function is creating three new objects with names that shadow the ones at file scope, so when you go to use the ones at file scope you get an access violation because they are never set to point at anything valid.

Your unique_ptr<Grid> in init is local to that function. The unique_ptr<Grid> will go out of scope at the end of the function, destroying itself and the Grid it owns. It seems like you want to actually have a global object unique_ptr<Grid> theGrid; which replaces the Grid* theGrid; you've got at the momement. Then in init you can do:
theGrid.reset(new Grid(offset));
The theGrid that is being accessed in display is the global theGrid of type Grid*.
The exact same is true for the other unique_ptrs you've tried to create.
Of course, rather than a global object, it would be much better to be passing these objects around, but your use of GLUT makes that a bit painful.

Related

Why declare a pointer in SDL before initializing SDL?

In this code, I see that they declare a pointer before initializing SDL:
int main(int argc, char* argv[]) {
SDL_Window *window; // Declare a pointer
SDL_Init(SDL_INIT_VIDEO); // Initialize SDL2
// Create an application window with the following settings:
window = SDL_CreateWindow(
"An SDL2 window", // window title
SDL_WINDOWPOS_UNDEFINED, // initial x position
SDL_WINDOWPOS_UNDEFINED, // initial y position
640, // width, in pixels
480, // height, in pixels
SDL_WINDOW_OPENGL // flags - see below
);
(full code can be found here)
Wouldn't it be more organized to declare the pointer right before you create a window, just so it would be neater and more organized? Why declare it beforehand?
If I would take a guess, it's good to just have all the pointers in one area, so you can see all the pointers at one time. Or is it just a good habit to get used to?
The habit of declaring pointers at the beginning of int main(). (I've also seen this happen in other source programs, from example programs)
There is no technical reason why you need to declare a pointer before SDL_Init. Declaring a pointer variable carries no implications with it, it just reserves space on the stack for that pointer. It could just as easily be declared after SDL_Init, or as part of the statement that calls SDL_CreateWindow.
I honestly don't know why they put it that way in the docs.

Vector is crashing my program

I've got a serious problem with my SFML game.
I've been trying whole day to find a solution, tried diffrent things but nothing worked for me so far.
These are my .h files:
Bullet.h
#pragma once
#include <SFML\Graphics.hpp>
#include <iostream>
#include <vector>
class Bullet
{
friend class Player;
friend class Game;
float width;
float height;
float x;
float y;
std::vector<Bullet*> projectiles;
sf::RectangleShape bullet;
void draw_projectiles(sf::RenderWindow &window);
void make_projectiles();
public:
void check();
Bullet();
~Bullet();
};
Game.h
#pragma once
#include <SFML\Graphics.hpp>
#include "Player.h"
#include "Bullet.h"
#include <vector>
//#include "Enemy.h"
class Game
{
friend class Player;
sf::RenderWindow* window;
sf::Event* evnt;
Player* player;
Bullet* bullet;
public:
void Loop();
void game_func();
Game();
~Game();
};
Player.h
#pragma once
#include <SFML\Graphics.hpp>
#include <iostream>
#include "Game.h"
#include "Bullet.h"
class Player
{
sf::RectangleShape player;
Bullet* bullet;
int ammo;
float width;
float height;
int x;
int y;
float vel;
public:
void draw(sf::RenderWindow &window);
void move(sf::Event &evnt, sf::RenderWindow &window);
Player();
~Player();
};
Here come cpp files
Bullet.cpp
#include "Bullet.h"
void Bullet::check()
{
x = bullet.getPosition().x;
y = bullet.getPosition().y;
}
void Bullet::draw_projectiles(sf::RenderWindow &window)
{
for (int i = 0; i < 10; i++)
{
window.draw(projectiles[i]->bullet);
}
}
void Bullet::make_projectiles()
{
projectiles.push_back(new Bullet());
}
Bullet::Bullet()
{
std::cout << "zostal utworzony nowy obiekt" << std::endl;
width = 50;
height = 50;
bullet = sf::RectangleShape(sf::Vector2f(width, height));
bullet.setFillColor(sf::Color::Yellow);
bullet.setPosition(0, 0);
x = bullet.getPosition().x;
y = bullet.getPosition().y;
}
Bullet::~Bullet(){}
Game.cpp
#include "Game.h"
Game::Game()
{
window= new sf::RenderWindow(sf::VideoMode(1280, 720), "SFML Game",
sf::Style::Close);
player = new Player();
}
Game::~Game(){}
void Game::Loop()
{
while (window->isOpen())
{
sf::Event evnt;
while (window->pollEvent(evnt))
{
//events
if (evnt.type==sf::Event::Closed)
window->close();
player->move(evnt, *window);
window->clear();
player->draw(*window);
window->display();
bullet->draw_projectiles(*window);
}
}
}
void Game::game_func()
{
Game::Loop();
}
Player.cpp
#include "Player.h"
void Player::draw(sf::RenderWindow &window)
{
window.draw(player);
}
void Player::move(sf::Event &evnt, sf::RenderWindow &window)
{
x = player.getPosition().x;
y = player.getPosition().y;
float width = window.getSize().x;
float height = window.getSize().y;
Bullet obj;
if (evnt.type == sf::Event::KeyPressed)
{
//movement
if (evnt.key.code == sf::Keyboard::Key::W)
{
if (y <= 0)
{
return;
}
player.move(0, -1 * vel);
}
if (evnt.key.code == sf::Keyboard::Key::S)
{
if (y >= height - Player::height)
{
return;
}
player.move(0, 1 * vel);
}
if (evnt.key.code == sf::Keyboard::Key::A)
{
if (x <= 0)
{
return;
}
player.move(-1 * vel, 0);
}
if (evnt.key.code == sf::Keyboard::D)
{
if(x>width-Player::width)
{
return;
}
player.move(1 * vel, 0);
}
if (evnt.key.code == sf::Keyboard::Space)
{
obj.make_projectiles();
}
}
}
Player::Player()
{
width = 100;
height = 100;
vel = 10;
player = sf::RectangleShape(sf::Vector2f(width, height));
player.setFillColor(sf::Color::Red);
player.setPosition(sf::Vector2f(15, 20));
}
Player::~Player(){}
And main.cpp
#include <SFML/Graphics.hpp>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include "Game.h"
int main()
{
Game gme;
gme.game_func();
return 0;
}
I tried many diffrent things and can't figure it out why it's not working. Im running in on Visual Studio 15.
So here is error that I'm getting:
Exception thrown: read access violation.
std::_Vector_alloc<std::_Vec_base_types<Bullet *,std::allocator<Bullet *> >
>::_Mylast(...) returned 0x18.
I'm aware that code is not perfect and little messy but I'm just a begginer and trying to learn new stuff.
I will appreciate any help!
I answered your question in my last paragraphs, you can skip to that paragraph but I sugest you take a look at all of this. First of all you should understand how should a basic game look like in code.
The Game Logic
You can separate the game logic in 2 main functions. The initialization and the loop.
Initialization
In the initialization function, you basically load everything needed for your game to run (that is only available for small games, since loading tens of gigs of sprites in memory may not be the best solution for bigger ones. With time you'll figure out the right time to load and release resources).
The loop
This is called the main loop or the game loop. This loop should execute 3 main functions. Handle user input, update world, and render the world. This loop should execute while the game is running (i.e. while the window is open)
So your main in pseudo-c++ should look something like this:
Init();
while (window.isOpen())
{
HandleEvents(window); //user input
Update(elapsedTime);
Render(window);
}
I'll explain what the functions do, what the arguments mean and how this functions are mapped to your code. Keep in mind that every function has one specific task and only that. I won't check if the user is pressing a button while I'm drawing the sprites on the screen.
User input
Everything from button pressing and mouse clicking to pressing the exit button and resizing the window is called user input. User's actions generate the so called events, which we handle at the beginning of each loop. Now this events are window specific(you can't control the player if the window is minimized or unfocused). That means that the window generates the events (if I'm wrong with this one technically, please correct me). This is the reason that when you are handling events you need to pass the window.
Events
Before handling the events, you need to understand how sf::Event is made (see more on the sfml page). Long story short the sf::Event is an union (only one field is valid at a time). That is, if you try to access event.key when the window.pollEvent() returned an sf::Event::JoystickEvent you will get an undefined behavior (I lived a long happy life without knowing what unions are, never used them and probably never will, but they are quite an interesting concept that is worth at least reading about). Ok so an event object is created by calling window.pollEvent() and passing to it an sf::Event instance. This function will give you events from the queue until there are no more events to be given, that's when it returns false. With that in mind, your Event handling code would look something like:
sf::Event ev;
while (window.pollEvent(ev))
{
switch (ev.type)
{
//code for each type needed by your application
}
}
Keep in mind that key events do not handle real time input (sf::Keyboard::isKeyPressed does that). This means that if you want your character to move when you hold a button, handling it by events will result in a delay that can be the best explained by the way typing works(when you hold down 'a' for example the first character is written immediately, the rest of the input is delayed by a second before registering). This is a way of explaining it, but maybe not the most technical one(I'm asking for a little help here :) ). Anyway, this problem can be solved either by using the static methods of sf::Keyboard or by keeping a bool in your Player class that answers to the events KeyPressed and KeyReleased(the update will be handled based on that bool).
World Update
Here is your logic code(although player movement may also be handled in the events section, since it's based on them). Here you update your entities(move the enemy one more block based on his AI), move the sun around the map etc. Keep in mind that this has nothing to do with the drawing part, in this section you only change the state of your objects. In your game it means, after you launched a projective through an event triggered by the user, each frame you move the projectile. This code usually requires some sort of frame counting method.
Frames
A frame is an iteration of the loop, you can say that the game updates and draws itself each frame. Frames are a very important concept because they arise some issues. If the game updates itself each frame, that means that each frame the projectile is moving, so that means that his movement is dependent to the FPS your pc can run. This is a problem, because while your game may run as you want on your pc, at a stable 60 FPS rate, on mine it might run at 53, or some other random value. That means that the projectiles on my pc will move slower, and we don't want that.
Frame independent movement
This can be achieved by counting the frames. One way you can do that is by counting the seconds it passed since the last frame, with that in mind you can get the amount of space your entity needs to move in that specific frame. For example, you want to move your projectile with 100px/sec. If you have 2FPS that means that in 2 frames it needs to move 100px, so each frame moves 100 / 2 px. So the formula is finalDistance / framerate. There are more ways of doing this, but in my opinion this is the simplest to understand at the beginning. So how is this implemented in SFML? You basically keep a clock that you restart at the end of each update. getElapsedTime and restart does that, but restart returns the elapsedTime so it is better to call it once, since calling them one by one may result in different times and desyncs.
sf::Clock clock;
while (window.isOpen())
{
HandleEvents(window);
Update(clock.restart());
Render(window);
}
And you simply move your entities with move(vector * clock.getElapsedTime().asSeconds()) since sf::Vector has operator* overloaded for floats(the return type of asSeconds()).
Rendering
The rendering part may be very complicated, but sfml makes it "simple and fast". Basically it works like that: You clear the screen, you draw your entities, you display the screen. The more technical answer is the following: the window consists of 2 buffers, one visible and one hidden. The visible one is the one you see on the screen. When you call clear() you basically clear the hidden one, draw() draws also on the hidden window, and finally display() swaps the buffers.
That means that you won't see any results unless you call window.display(), and you'll get a window xp experience if you don't call clear() before drawing. So the Render function might look like this:
window.clear();
window.draw(player); //or player.draw(window) based on your implementation
//other draws
window.display();
Your question
What happens in your code is that you try to access things that don't exist. You add one projectile at a time, but each frame you draw 10 of them.
The solution
Keep a counter of your objects. Since you are using a vector that is already provided, you have std::vector::size that returns exactly what you expect, so your code will turn into something like:
for (int i = 0; i < yourProjectiles.size(); i++)
{
window.draw(yourProjectiles[i]->bullet);
}
Alternatively you can use iterators(look them up):
for (auto it = yourProjectiles.begin(); it != yourProjectiles.end(); ++it)
{
window.draw(it->bullet);
}
Memory management
You don't deallocate memory. You have to look into dynamic memory allocation. The base principle is that for every new there should be a delete. The deallocation part should be handled most of the time in the destructor of the class. I think someone may suggested to use smart pointers(std::shared_ptr) so manage your memory, but I can't recommend you that since you are at the beginning. Smart pointers are a concept you should keep in mind, but as you started out it is better to face the struggles of manual memory management(until you get used to it).
Code organizing
A class should be made for only one purpose. When you create a class called Bullet, it is expected that this Bullet will represent one projectile in your game, but when your Bullet makes "projectiles" and stores projectiles, it becomes a paranormal entity. Your bullet atm holds pointers to instances of other bullets that hold pointers to instances of other bullets. This is a total mess. Unless you want to create a graph or a tree of some sort you don't have any reason to store pointers of instances of the same class.
Too many friends
If every class is friend with every class, what is your reason of creating private fields? Friend is a very powerful concept and should be used with care, only in cases you DON'T have other options. The only reason I would avoid this keyword is the messiness it creates. It creates the same effect as public attributes. When everything is accessible from everywhere, everything can be destroyed from everywhere. When you create a small set of methods that manipulate your attributes, you know where the problem is.
Conclusion
I might suggest looking a little more into c++ and after that debug your game, or recreate it from scratch. While I know how it feels to try something new, you should always be careful to not shoot yourself in the leg, and don't be afraid to go back to the basics when you stumble into such errors. You have problems managing memory? Read more about dynamic memory allocation, do some example apps using it. Besides that I noticed you are still at the beginning with using classes. I'd say practice makes perfect. Look at other people code, even these 3rd party libraries like sfml may give you some hints on good class practices. The good thing is that it is not needed to look at the source code of those libraries, you just use their interface. If you like it, it means it is good written and you may borrow a part of that style and implement in your classes. I'll conclude this by saying that I am very happy and eager to help you via email if you have any other question regarding anything.
I believe you are attempting to access ten projectiles:
for (int i = 0; i < 10; i++)
{
window.draw(projectiles[i]->bullet);
}
But you only add one at a time:
projectiles.push_back(new Bullet());

How to call an external c-function, while a GLUT Display Loop locks my c++ main?

I'm new here and not so familiar with display programming.
I have a c-Program that calls a doStep-function every 40ms. Within this function I have C++ Code, which runs a glut display to visualize a 3D-environment. The doStep function passes new position information of my 3D Objects from outside into my C++ 3D-environment.
The problem is, that my c-code gets locked by the glut display loop, so that I can't update the positions in the environment any more. Should I use a seperate thread for the display loop for solving this issue?
I know that glutPostRedisplay() can be used to redraw my scene, but I don't know how to separate my display loop to maintain control of the doStep function.
Thanks in advance
Ok since my post was unclear and without code, I will try to specify the issue. I'm using Nvidia OptiX Raytracing for rendering a scene. The visual output is created by a GLUTDisplay class in C++. I created a separate thread for my display and detached it, so that I have further control of the program. I know that one can share a class between threads, so it was possible for me to create a separate thread for the display and calling GLUTDisplay::postRedisplay(); in my other thread to update the context. To run my program I use 3 c-functions:
extern "C" {
extern void* create(const char* filename, double* inputArray, double* outputArray, int argc, char** argv);
extern void trace(void* scene_obj);
extern void exitScene(void* scene_obj);
}
Here's my implementation of them:
void * create( const char* filename, double* inputArray, double* outputArray, int argc, char** argv ){
OptixScene* scene = new OptixScene(filename);
scene->routeInput(inputArray); //routing my inputs and outputs
scene->routeOutput(outputArray); //from a simulation model
std::thread display_thread(&OptixScene::createDisplayThread, scene, argc, argv); // this starts the display loop
display_thread.detach(); // detach display thread to get control back
return (void *)scene;
}
void trace( void* scene_obj ){
OptixScene* scene = static_cast<OptixScene*> (scene_obj);
scene->readInputs();
scene->updateMatrix();
scene->renderImage(); // GLUTDisplay::postRedisplay() in here
scene->writeOutputs();
}
void exitScene(void* scene_obj){
OptixScene* scene = static_cast<OptixScene*> (sensor);
try{
scene->cleanUp();
if (scene->getContext().get() != 0)
{
sutilReportError( "Scene class failed to clean up!" );
exit(2);
}
exit(0);
}
catch( Exception& e ){
sutilReportError( e.getErrorString().c_str() );
exit(2);
}
}
At the beginning I call create() once and then every 40ms I call trace() to update my scene. Is this a safe thread implementation for the dislay loop? After a while running my progam, my scene won't update itself anymore. Only if I'm moving my mouse over the window, the scene gets updated. Is this caused by my thread implementation?
To mix C code with C++ code, use the extern keyword.
extern "C"{
void externalDoStep() {
// your algorithm here
}
}
However when you say that your function is being blocked, i think you should do this:
Try plugging your doStep() function into this GLUT callback function just to see..
glutIdleFunc( doStep );
or any other GLUT callback function.
If you dont put your functions in a GLUT callback function, your function will not be run by GLUT.
The main important part of GLUT are the callbacks. These are functions that will handle the GLUT events generated when you change the size of the window or press a key.
It works like this. You create your own functions and plug those function
into these main GLUT callback functions. They must be in the main()
glutReshapeFunc(your reshape function);
glutDisplayFunc(your display function);
glutIdleFunc(your idle function);
glutKeyboardFunc(your keyboard function);
Full Code listing:
#include <windows.h>
#include <string.h>
#include <GL\glut.h>
#include <iostream.h>
#include <fstream.h>
#pragma comment(lib, "glu32.lib")
int ii=0;
int iex=0;
extern "C"{
void externalDoStep() {
// your algorithm here
iex++;
cout<<iex<<" externalDoStep \n";
}
}
void doStep (void){
// your algorithm here
ii++;
cout<<ii<<" doStep () is running \n";
glutPostRedisplay();
}
void RenderToDisplay(){
// your algorithm here
}
void myDisplayFunction(void){
// your algorithm here
}
void myReshapeFunction(int w, int h){
// your algorithm here
}
int main(){
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 400);
glutCreateWindow("dostep");
glClearColor(0.0, 0.0, 0.0, 1.0);
glLineWidth(3);
glutDisplayFunc( myDisplayFunction );
glutReshapeFunc( myReshapeFunction );
glutIdleFunc( doStep );
glutMainLoop();
return 0;
}

Access violation reading location 0x00000004

I have a Class Player like this:
class Player
{
public:
Player();
~Player(void);
Sprite *sprite;
Sprite *rocket;
void draw(int x, int y, SpaceInvaders *system);
}
and in Player.cpp
void Player::draw(int x, int y, SpaceInvaders *system) {
sprite = system->createSprite("data/player.bmp");
sprite->draw(x, y);
}
Player::~Player(void)
{
sprite->destroy();
rocket->destroy();
}
This draw method is called in a while loop in main:
player.draw(int(xPos), 480-32, system);
The game runs fine until I X the window. That's when I get "Access violation reading location 0x00000004" on the first line in the Player::draw method.
I've read that it might be due to passing a null pointer or null reference but I don't know how to fix this.
Would appreciate any help, thanks!
It's most probably because when closing the window, something gets destroyed while draw is called - most probably the system pointer.
In your case, draw should never be called when the user wants to close its window (unless the x calls another function to start a closing process of some sort). The best would be to first validate that system is not NULL or even better, use a shared pointer to ensure it is still valid when being used. Afterwwards, you shoiuld ensure that draw is not called when the window is closing - that should be done when calling the draw function (or above depending on how you've designed your application.
On a side note, unless you have a caching mechanism (and even that is not the best way to do it), you're recreating your sprite everytime it's being drawn. I suggest you keep a member variable and initialize the sprite in the construtor.

Prevent an Object from destroying prematurely

Here's the (relevant) code for my pro::surface class:
/** Wraps up SDL_Surface* **/
class surface
{
SDL_Surface* _surf;
public:
/** Constructor.
** #param surf an SDL_Surface pointer.
**/
surface(SDL_Surface*);
/** Overloaded = operator. **/
void operator = (SDL_Surface*);
/** calls SDL_FreeSurface(). **/
void free();
/** destructor. Also free()s the internal SDL_Surface. **/
virtual ~surface();
}
Now the problem is that in my main function, the object destroys itself (and hence calls the destructor which dangerously free()s the SDL Video Surface!) before the real rendering begins.
int main(int argc, char** argv)
{
...
// declared here
pro::surface screen = SDL_SetVideoMode(320,240,16,SDL_HWSURFACE|SDL_DOUBLEBUF);
// event-handling done here, but the Video Surface is already freed!
while(!done) { ... } // note that "screen" is not used in this loop.
// hence, runtime error here. SDL_Quit() tries to free() the Video Surface again.
SDL_Quit();
return 0;
}
So my question is, is there any way to stop the pro::surface instance from destroying itself before the program ends? Doing memory management manually works though:
/* this works, since I control the destruction of the object */
pro::surface* screen = new pro::surface( SDL_SetVideoMode(..) );
/* it destroys itself only when **I** tell it to! Muhahaha! */
delete screen;
/* ^ but this solution uses pointer (ewww! I hate pointers) */
But isn't there a better way, without resorting to pointers? Perhaps some way to tell the stack to not delete my object just yet?
You violated the Rule of Three, bitch.
pro::surface screen = SDL_SetVideoMode(320,240,16,SDL_HWSURFACE|SDL_DOUBLEBUF);
Is equal to
pro::surface screen = pro::surface(SDL_SetVideoMode(320,240,16,SDL_HWSURFACE|SDL_DOUBLEBUF));
Now double free, because you violated the Rule of Three. So give your class a proper copy constructor/assignment operator, or disallow them and explicitly construct it properly.
Edit: This also explains why your pointer version works fine- because you don't invoke a copy.
Wrap the screen in a special wrapper, that pairs SDL_SetVideoMode with SDL_Quit instead of SDL_FreeSurface.
pro::screen screen(320, 240, 16, SDL_HWSURFACE | SDL_DOUBLEBUF);
// ...
And fix your copy ctor, obviously.