SFML community forums

Help => Graphics => Topic started by: Xyro on September 02, 2011, 09:22:51 pm

Title: R6025 Error, pure virtual function call
Post by: Xyro on September 02, 2011, 09:22:51 pm
Hello, I got a problem where when I start my program it crashes with the R6025 error (link : http://support.microsoft.com/kb/125749 )

I managed to find what was causing it but no idea why :

Code: [Select]
void BaseEntity::Draw(float frameTime)
{
renderWindow->Draw(sprite);
}


which is in BaseEntity.cpp

Here is the header file :
Code: [Select]

#pragma once
#include <SFML\Graphics.hpp>

class BaseEntity
{
protected:
sf::RenderWindow * renderWindow;
public:
sf::Vector2<float> position;
sf::Sprite sprite;

BaseEntity();
BaseEntity(sf::Vector2<float>, sf::Sprite);
virtual void Draw(float);
virtual void Think(float);
};


Here is the object implementing baseentity :

Code: [Select]

#pragma once
#include <SFML\Graphics.hpp>
#include "BaseEntity.h"

class player : public BaseEntity
{
const sf::Input * input;
public:
// Physics variables :
sf::Vector2<float> velocity;
sf::Vector2<float> acceleration;
sf::Vector2<float> friction;
sf::Vector2<float> maxAccelerationSpeed;

player(sf::Vector2<float>, sf::Sprite, const sf::Input*, sf::RenderWindow *);
void Draw(float);
void Think(float);
};


Code: [Select]

#include "player.h"

player::player(sf::Vector2<float> pos, sf::Sprite spr, const sf::Input * inp, sf::RenderWindow * window) : BaseEntity()
{
//Physics :
velocity = sf::Vector2<float>(0,0);
acceleration = sf::Vector2<float>(5,5);
friction = sf::Vector2<float>(0.97f,0.97f);
maxAccelerationSpeed = sf::Vector2<float>(25,25);

position = pos;
sprite = spr;
input = inp;
renderWindow = window;
}

void player::Draw(float frameTime)
{
BaseEntity::Draw(frameTime);
}



I left out the think method since its only calculating physic related things.

Also I have a world class which just has a basic think and draw loop which is called all of the entity's in the scene (currently only a player entity)
I hope this is detailed enough and if not please tell me what you need. I also know this was causing this since I just removed the
Quote
renderWindow->Draw(sprite);

part and it didn't give the error.
Title: R6025 Error, pure virtual function call
Post by: Groogy on September 03, 2011, 03:04:05 am
Can you check with the debugger exactly what kind of object the pointer is pointing at?
If you trough the debugger dereference the pointer you should see the type. Also show us the code where render target is set for the player entity.

Also are you using SFML2 or SFML 1.6?
Title: R6025 Error, pure virtual function call
Post by: Xyro on September 04, 2011, 03:35:03 pm
I am using sfml 2.0, its pointing to a render window and what do you mean with : Also show us the code where render target is set for the player entity.
Title: R6025 Error, pure virtual function call
Post by: Groogy on September 04, 2011, 03:38:25 pm
Exactly what I said?

Code: [Select]
player::player(sf::Vector2<float> pos, sf::Sprite spr, const sf::Input * inp, sf::RenderWindow * window)

Show us the code where the argument window gets it's pointer.
Title: R6025 Error, pure virtual function call
Post by: Xyro on September 04, 2011, 03:41:05 pm
Ahh sorry

Code: [Select]
player(sf::Vector2<float>(10,10), sf::Sprite(sub), &world.GetWindow()->GetInput(), world.GetWindow())

from the world class :
Code: [Select]
sf::RenderWindow * GetWindow() {return &renderWindow;}
Title: R6025 Error, pure virtual function call
Post by: Groogy on September 04, 2011, 03:52:06 pm
And world has been properly initialized by that time?(Has exited the constructor of world)

Also try to create a minimal example where it happens so we can try it out on our own machines.
Title: R6025 Error, pure virtual function call
Post by: Xyro on September 04, 2011, 05:07:03 pm
Hey, sorry for the late respone, my internet is broken I guess because it took like 30 min to upload this 10mb zip.

http://www.2shared.com/file/upsjLUmP/SFML.html

It contains the project with just the 3 classes : World, BaseEntity and player.
Title: R6025 Error, pure virtual function call
Post by: Groogy on September 04, 2011, 05:18:38 pm
Well you left out the most important part for when you added the player entity:

Code: [Select]
world.entityList.push_back(&player(sf::Vector2<float>(10,10), sf::Sprite(sub), &world.GetWindow()->GetInput(), world.GetWindow()));

What you do here is create a temporary player instance and then take the adress from it. The moment we enter the next line of code that object's memory is freed. Since you are running in Debug it probably get's nullified so it is all 0. And virtual methods needs the vtable to map to correct method in the class inheritance hierarchy but since the memory has been free'd the render target pointer points to 0 where there is no vtable so visual studio interprets it as a pure virtual function call.

That's my theory on what happens. But the bottom line. What you are trying to do there is a BIG NO NO.
Title: R6025 Error, pure virtual function call
Post by: Xyro on September 04, 2011, 08:31:28 pm
So, I yea this is really what happens, just tested, but how would one fix this ?

edit :

Oke well this worked :
Code: [Select]
sf::Image sub;
sub.LoadFromFile("Assets//submarine.png");
sub.CreateMaskFromColor(sf::Color::White);
player plyr1 = player(sf::Vector2<float>(10,10), sf::Sprite(sub), &world.GetWindow()->GetInput(), world.GetWindow());

world.entityList.push_back(&plyr1);


Is this the proper way to do it ?
Title: R6025 Error, pure virtual function call
Post by: Groogy on September 04, 2011, 08:43:31 pm
Not really. But explaining why and how to do it would in my opinion require a whole article on Object Oriented Design. At least I would write that and I don't think you are very interested in reading a huge document about why that is wrong.

I'll try to summarize with: You are using a raw pointer when you don't need to. Just don't and try to come up with a better design ;)
Title: R6025 Error, pure virtual function call
Post by: Xyro on September 04, 2011, 08:55:06 pm
But if I didn't use pointer wouldn't it just call the underlying class his think / draw methods ?

I probably sound very stupid (obviously still learning) but could you point me out to some better design patterns for game development then ? This is just something I came up with because I saw xna has something that looks like this :P
Title: R6025 Error, pure virtual function call
Post by: Groogy on September 04, 2011, 09:03:40 pm
All I've learned is from experience and expensive books =/

So you'll have to hold your thumbs(Swedish version of cross your fingers) that there is someone else here that can either explain it better than me or know a good resource. Best I can recommend I guess is googling: http://www.google.se/search?q=Object+Oriented+Design
What you want is called Aggregation which is a fancy word for ownership and that is what you want your world to do, own the player. Something else that might help is read up on Design Patterns.
Title: R6025 Error, pure virtual function call
Post by: Laurent on September 04, 2011, 09:07:02 pm
You must allocate the player instance dynamically (with the "new" keyword) so that you control when it is destroyed, not the compiler. To destroy it, you must use the "delete" keyword. To avoid this manual management of instances, you can read articles/tutorials about "smart pointers".
Title: R6025 Error, pure virtual function call
Post by: Xyro on September 04, 2011, 09:09:01 pm
Thanks guys, I am going to read into this stuff and thanks for helping again :)
Title: R6025 Error, pure virtual function call
Post by: Fred_FS on September 04, 2011, 09:55:57 pm
I don't think that you have to do many changes. Of course you can read millions of articles, but probably your game will never be finished ;).
My suggestion is: Just try to do it your way and you will see, what are the assets and drawbacks and you will maybe use another system in your next project - or not, if your system works well for you.
What you want to do is probably programming a game and not winning design contests(of course a good design is necessary, but I don't think your design is that bad).

To solve your problem there are two solutions.

First:
Do not use any pointers. Just save a copy of the objects in your list. So you can create temporarily objects and they will be copied to the list and the old object will be deleted, but your copy will still remain. But in that case: Use references to get your objects from the list.
A small example:
Code: [Select]

class object_manager
{
public:
    object& get_object( unsigned int index );
private:
    std::list<object> objects;
}


Second:
You can still use pointers, but have to use pointers, if you create an object, too.
Example:
Code: [Select]

player* tmp_player = new player( sf::Vector2<float>(10,10), sf::Sprite(sub), &world.GetWindow()->GetInput(), world.GetWindow());
world.entityList.push_bakc(tmp_player);

But you have to delete the memory, if you want to delete an object(or all objects at the end of the game). Therefore simply call delete before removing an entity from your list.

Another point you have to think about is your image-management. In your code you're creating a temporary image "sub", which is destroyed, if the scope is left. The sprite would probably displayed as a white rectangle. So you should save your images as well. I wrote a tutorial about an image-manager a few months ago in the wiki: Have a look at it. (https://github.com/SFML/SFML/wiki/TutorialImageManager)

I don't think that you should read much about design-patterns but rather read some stuff about memory-handling in C++.