I am trying to have a class that contains a static list of pointers to instances of the class, but I am getting a memory leak. I was wondering if anyone could point out what is wrong with the following code. I have a feeling its either to do with the destructor, or the void creature::kill() function. I note that I am using allegro but have not included some functions which are not doing anything special.
Firstly the class header:
class creature{
private:
//some data for other functions
public:
static std::list<creature*> mycreatures;
creature();
~creature();
void kill();
};
the class .cpp file
#include "creature.h"
std::list<creature*>creature::mycreatures;
creature::creature(){
mycreatures.push_back(this);
}
creature::~creature(){
std::list<creature*>::iterator p =
find(mycreatures.begin(),mycreatures.end(),this);
if(p != mycreatures.end()){
mycreatures.erase(p);
}
}
void creature::kill(){
if(mycreatures.size()>0){
std::list<creature*>::iterator it = --mycreatures.end ( );
delete (*it);
}
}
and the main
#include "creature.h"
void main (void){
creature a;
while(!key[KEY_ESC]){
std::list<creature*>::iterator it;
for(it=a.mycreatures.begin(); it!=a.mycreatures.end(); it++)
{
(*it)->//some other non included functions
}
if(key[KEY_N]){
new creature();
}
if(key[KEY_K]){
a.kill();
}
}
allegro_exit();
}
END_OF_MAIN();
creature a;
Ack! You have code that calls delete on a creature without calling new on that creature. For this to work, you must always create creatures using new and never create them on the stack! What happens if this creature is killed while it's still in scope? Boom.
Related
I have wondered that both c++ and java using oops concepts but the syntaxes are quite different.
I found that java uses new ClassName() to get a reference to the heap but getting the same reference to the heap why the c++ uses new ClassName.
#include<iostream>
using namespace std;
class Bike
{
public:
virtual void run()
{
cout << "running";
}
};
class Splender :public Bike
{
public:
void run()
{
cout << "running safely with 60km";
}
};
int main()
{
Bike &obj = new Splender();//error but reason?
obj.run();
}
ERROR:
invalid initialization of non-const reference of type 'Bike&' from an rvalue of type 'Splender*'
Two things. One: Operator new returns a pointer, not a reference, to an object instance. So use Bike* obj = new Splender();
Two: Do not get cute and try Bike& obj = *new Splender(); because new can return nullptr in a low memory situation and if you dereference it, your program will crash at that point. (And you are forced to use the ugly delete *obj; to clean up this object as user4581301 points out in the comments.)
Oh, and using namespace std is a bad practice. It won't kill you to add std:: in the places you use the standard library.
Sometimes we think doing the right thing.
You make a bit confusion. Try:
Bike *obj=new Splender();
#include <iostream>
class Bike {
public:
virtual void run() {
std::cout << "running";
}
virtual ~Bike() {}
};
class Splender: public Bike {
public:
void run() override {
std::cout << "running safely with 60km";
}
};
int main() {
Bike *obj = new Splender(); // new returns a pointer to a dynamically allocated object
obj->run();
delete obj;
}
which displays:
running safely with 60km
I apologize if this is a lot of code to read, if I can simplify with explanations please let me know, also if you'd like to comment on my design/practices feel free.
So my Player is being deleted twice, I'm not sure why. If you look at the call stack, you'll see that GameEventManager is actually calling the Player destructor before the GameState destructor, even though GameState is the one with the pointer to Player. I'm thinking maybe this is because it's also destroying the vector first, so it finds Player in the vector and tries to destroy it. I don't know why it would try to destroy the Player though, since there is still a reference to Player that the GameState object knows about. The shared pointer functionality should prevent the Player from being destroyed.
Maybe I am going about it the wrong way, if so could someone point me in the correct direction for best practices here? Thanks
Call stack:
GameState.h
#ifndef _level
#define _level
#include <vector>
#include "Player.h"
#include <memory>
using namespace std;
class GameState // A representation of the Level/Game/Scene
{
public:
GameState();
virtual ~GameState() {}
//Keep track of the game's state
//Maybe get rid of the Level class, and make this a class, and move the Level functionality here?
static void EndGame(const bool & b) { mbEndGame = b; }
static const bool & EndGame() { return mbEndGame; }
private:
void SetPlayer(shared_ptr<Player> sptrPlayer) { msptrPlayer = sptrPlayer; }
static bool mbEndGame;
shared_ptr<Player> msptrPlayer;
vector<shared_ptr<Player>> msptrMob; // Representation of all the NPCs in the game. Eventually make a Mob class but for now just use Player
// shared_ptr<LevelMap> mMap // Representation of what the game looks like visually
// Renderer // Should the level have the renderer to create the graphics? Or should this be handled by another "GUI Layer" and interact with this layer as little as possible ?
};
#endif
GameState.cpp
#include "stdafx.h"
#include "GameState.h"
bool GameState::mbEndGame(false);
GameState::GameState() : msptrPlayer(NULL)
{
shared_ptr<Player> sptrPlayer(new Player);
SetPlayer(sptrPlayer);
}
GameObject.h
#ifndef _game_object
#define _game_object
#include <memory>
// Game Object Classes inherit this so they are registered with GameEventManager.
using namespace std;
class GameObject{
public:
GameObject();
virtual ~GameObject() {}
virtual void Update() = 0;
virtual void Start() = 0;
};
#endif
GameObject.cpp
#include "stdafx.h"
#include "GameObject.h"
#include "GameEventManager.h"
GameObject::GameObject()
{
shared_ptr<GameObject> ptr(this);
GameEventManager::GetGameEventManager()->RegisterGameObject(ptr);
}
Player.h
#ifndef _player
#define _player
#include "GameObject.h"
//A representation of the Player. Used by Level.
class Player : public GameObject
{
public:
Player();
virtual ~Player() {}
private:
virtual void Update();
virtual void Start();
int miMaxHealth;
};
#endif
Player.cpp
#include "stdafx.h"
#include "Player.h"
#include "GameState.h"
Player::Player() : miMaxHealth(100) {};
void
Player::Start()
{
}
void
Player::Update() // reimplement GameObject::Update(), which is called by the GameEventManager
{
--miMaxHealth;
if (miMaxHealth <= 0)
{
GameState::EndGame(true);
}
}
GameEventManager.h
#ifndef _game_event_manager
#define _game_event_manager
#include "stdafx.h"
#include <memory>
#include <vector>
#include "GameObject.h"
#include "GameState.h"
using namespace std;
class GameEventManager{
//Object which inherit from GameObject are automatically registered with GameEventManager when they are constructed.
// GameEventManager creates the level object to represent the game, and then runs Start() on all registered GameObjects
// and then continually runs Update() on all registered game objects until the GameState is set to EndGame.
public:
virtual ~GameEventManager(){} // This gets called at the end of the program (I guess whne static variables are destroyed), and crashes during vector<shared pointer <GameObject>> destruction, probably because
// Player already destroyed it. So... not sure what to do. If I make it non-static
void StartGameEvents();
const static shared_ptr<GameEventManager>& GetGameEventManager();
const shared_ptr<GameState>& GetLevel();
void RegisterGameObject(shared_ptr<GameObject> sptrGameObject);
const shared_ptr<vector<shared_ptr<GameObject>>>& GetRegisteredGameVector() const { return mvecRegisteredGameVector; }
private:
GameEventManager(); //singleton
void AddGameObject(shared_ptr<GameObject>);
shared_ptr<GameState> mLevel;
shared_ptr<vector<shared_ptr<GameObject>>> mvecRegisteredGameVector; //Reference because shared pointer will double delete otherwise. ~Level() still deletes it but this way I guess it doesn't try to delete again? but...
//Now I'm trying it as a shared_ptr, but it's not working. ~Level() still deletes it even though there is a shared pointer to a vector pointing to the Player. Why is ~Level() doing this?
static shared_ptr<GameEventManager> msptrGameEventManager;
};
#endif
GameEventManager.cpp
#include "stdafx.h"
#include "GameEventManager.h"
#include "GameState.h"
shared_ptr<GameEventManager> GameEventManager::msptrGameEventManager(new GameEventManager);
void
GameEventManager::StartGameEvents()
{
//run once
int size = GetRegisteredGameVector()->size();
vector<shared_ptr<GameObject>> & vecsptrRegisteredGameVector = (*GetRegisteredGameVector());
for (int i = 0; i < GetRegisteredGameVector()->size(); ++i)
{
vecsptrRegisteredGameVector[i]->Start(); //nothing for now
}
//keep running
while (GetLevel()->EndGame() != true)
{
for (int i = 0; i < GetRegisteredGameVector()->size(); i++)
{
(*GetRegisteredGameVector())[i]->Update(); //Player's life goes from 100 to zero, see Player::Update
}
}
return;
// GameState destructor is called and destroys player for some reason, even though it's still being referenced by the GameEventManager's vector.
}
GameEventManager::GameEventManager() : mvecRegisteredGameVector(new vector<shared_ptr<GameObject>>) , mLevel(NULL) //Instantiating the level before the GameEventManager is fully instantiated causes an infinite recursion.
{
return;
}
const shared_ptr<GameEventManager>&
GameEventManager::GetGameEventManager()
{
if (!msptrGameEventManager)
{
msptrGameEventManager.reset(new GameEventManager);
}
return msptrGameEventManager;
}
const shared_ptr<GameState>&
GameEventManager::GetLevel()
{
if (!mLevel)
{
mLevel.reset(new GameState);
}
return mLevel;
}
void
GameEventManager::RegisterGameObject(shared_ptr<GameObject> sptrGameObject)
{
GetGameEventManager()->AddGameObject(sptrGameObject);
}
void
GameEventManager::AddGameObject(shared_ptr<GameObject> sptrGameObject)
{
GetRegisteredGameVector()->push_back(sptrGameObject);
}
GameObject::GameObject()
{
shared_ptr<GameObject> ptr(this);
GameEventManager::GetGameEventManager()->RegisterGameObject(ptr);
}
The ptr in this function does not share ownership with any other shared_ptr constructed independently, like the one declared at shared_ptr<Player> sptrPlayer(new Player);. Creating two shared_ptr from raw pointers, rather than copying the first one, generally leads to a double delete.
Instead, you could do something like this:
class GameObject :
public std::enable_shared_from_this<GameObject>
{
protected:
GameObject(); // creates the original shared_ptr
virtual ~GameObject();
};
class Player : public GameObject
{
public:
static std::shared_ptr<Player> create();
private:
Player() : GameObject() {}
virtual ~Player() {}
};
std::shared_ptr<Player> Player::create() {
return dynamic_pointer_cast<Player>((new Player)->shared_from_this());
}
A player is inherited from a GameObject (class Player : public GameObject). During the gamestate construction, it is set as the player.
GameState::GameState() : msptrPlayer(NULL)
{
shared_ptr<Player> sptrPlayer(new Player);
SetPlayer(sptrPlayer);
}
You add the object to a std::shared_ptr object. But, the parent class GameObject also creates a std::shared_ptr object, and adds the same pointer:
GameObject::GameObject()
{
shared_ptr<GameObject> ptr(this);
GameEventManager::GetGameEventManager()->RegisterGameObject(ptr);
}
The same pointer is added to two separate std::shared_ptr objects. So both shared pointer objects will delete the object, causing your problem.
I am having a problem with the following code, the overriden virtual functions are not executing. Not sure i'm doing wrong here probably a silly mistake. Anyway this is a game project and I have an array of objects which looks like this (the core::array is an irrlicht array, similar to the vector array)
core::array<GameObject> gameTargets;
This is the GameObject and Zombie definition
class GameObject {
protected:
scene::ISceneNode* node;
public:
int ID;
int hitpoints;
GameObject() {
...
};
void setNode(scene::ISceneNode* inode) {
...
}
virtual void shot(int dmg) {
... [BREAKPOINT HERE]
}
scene::ISceneNode* getNode() {
return node;
}
};
class Zombie : public GameObject {
public:
static const enum Animation {
ZOMBIE_WALK,
ZOMBIE_HURT,
ZOMBIE_DIE,
ZOMBIE_TWITCH,
ZOMBIE_ATTACK,
ZOMBIE_IDLE
};
//We only want to accepted animated mesh nodes for this object
Zombie(int hp, scene::IAnimatedMeshSceneNode* inode) {
...
}
//Override the shot function
void shot(int dmg) {
... [BREAKPOINT HERE]
}
//Animate the zombie
void setAnimation(Animation anim) {
...
}
};
The member functions of the derived classes is never called, I am creating the objects like this
Zombie target(hp, (scene::IAnimatedMeshSceneNode*)node);
and calling the virtual function like this
for(int i = 0; (u32)i<level->gameTargets.size(); i++) {
if(selectedNode == level->gameTargets[i].getNode()) {
level->gameTargets[i].shot(b->damage);
}
}
where b is a pointer to a bullet with a int variable damage and gameTargets contains GameObject
I suspect that you're experiencing slicing because the gameTargets array contains values. I can't tell for sure because I don't know how the core::array template works. See What is object slicing? for a discussion about what slicing is.
To fix this problem, store either raw pointers as in
core::array<GameObject *> gameTargets;
Or use some sort of reference-counted pointer like
core::array<std::shared_ptr<GameObject>> gameTargets; // only available in C++11
array<GameObject> is a container of objects, not a container of pointers. Every object you add to it will be a GameObject and not one of the derived classes (if you add a derived class object, then it'll be "sliced").
Without knowing exactly what your core::array does, I suspect what you really intended to create is an array of std::unique_ptr<GameObject> (smart pointers) along the lines of
core::array< std::unique_ptr<GameObject> > gameTargets;
std::unique_ptr<GameObject> my_zombie(new Zombie);
gameTargets.push_back( my_zombie );
a quick solution would be to make those parent functions as pure virtual functions, as in:
virtual void shot(int dmg) { } = 0;
// edit
and use array of pointer as suggested by Frerich Raabe
What's the difference between doing,
EventList temp;
EventList* temp = new EventList();
Where now temp you access it's vars by doing using .
and the other is ->
Besides that difference, what else? Pointer allocates on the heap while just EventList is on the stack. So is it primarily a scope thing?
There is short summary
Object on the stack EventList temp;
access is little bit faster, there is no derefferencing
object are automatically deleted at the end of method which creates them so we don't have to care about their deletion
stack size is limited ( much more than heap )
these objects cannot be returned from the method without copying
Object on the heap EventList* temp = new EventList();
heap is "unlimited" ( comparing to stack )
these objects are easilly shared accross whole application because they aren't automatically deteled
we have to delete them manually, if we loose the pointer then there are lost bytes in memory ( leaks )
Eventlist temp is allocated and deallocated automatically within the scope in which it is called. That is, when you run the following code:
{
EventList temp;
}
The default constructor for EventList is called at the point of its declaration, and the destructor is called at the end of the block.
EventList *temp = new EventList(); is allocated on the heap. You can read more about it here.
Well, from that example, there are only things that you have noted that are differences, but when using virtual functions and inheritance you'll see differences.
For example, here is the same code with pointers and without:
WITH POINTERS:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void Create()
{
cout <<"Base class create function ";
}
};
class Derived : public Base
{
public:
void Create()
{
cout<<"Derived class create function ";
}
};
int main()
{
Base *x, *y;
x = new Base();
y = new Derived();
x->Create();
y->Create();
return 0;
}
OUTPUT:
Base class create function
Derived class create function
WITHOUT POINTERS:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void Create()
{
cout <<"Base class create function ";
}
};
class Derived : public Base
{
public:
void Create()
{
cout<<"Derived class create function ";
}
};
int main()
{
Base x, y;
x.Create();
y.Create();
return 0;
}
OUTPUT:
Base class create function
Base class create function
So there are problems with objects and virtual functions. It is executed base class function when derived one should be. That is one of differences.
I'm trying to structure my code like this main <- game <- player.
IF I write in main:
player* P;
P = new player;
P->move();
Everything works but when trying to move this code in to the game component I run in to problems.
Here is the parts of game.cpp I need help with.
#include "game.h"
#include <string>
using namespace std;
game::game(){
player* P;
P = new player;
};
void game::playerStuff(){
P->move(); //c2227+C2065
};
Here is a part of game.h
#include "player.h"
class game {
public:
game();
void playerStuff();
The issue is rather simple. Your pointer to the player (P) is a local variable only visible/existing within your constructor. Add it as a class member instead to use it everywhere in your game class:
class game
{
private:
player *P;
public:
game();
// other stuff ...
}
P needs to be a member of the game class.
Currently, in your constructor here:
game::game(){
player* P;
P = new player;
};
P is local to the ctor and disappears as soon as this function ends.
Solution
Make P a member of game:
class game {
private:
player * P;
public:
game();
~game(); // NOTE: I have added a destructor
void playerStuff();
}
And change the contructor:
game::game(){
P = new player;
};
Remembering of course, to delete it in the destructor:
game::~Game(){
delete P;
};
Of course, because you include <player.h>, you don't need to allocate this object on the heap at all, and can use the stack instead, thereby negating the need to delete P in the destructor.
EDIT: Here is an example showing using the stack, rather than allocating on the heap:
#include "player.h"
class game
{
private:
player P; // Note, we're not declaring a pointer.. we have a complete type here.
public:
game();
~game();
void playerStuff();
}; // eo class game
game.cpp
game::game()
{
// No need to allocate, it's already allocating on the stack
}; // eo ctor
game::~game()
{
// No need to delete, P will be deallocated along with this game class.
}; // eo dtor
void game::playerStuff()
{
P.move(); // note we're not using -> (pointer to member) here
} // eo playerStuff
Move #include "player.h" to game.cpp if you need only pointers or references on game.h. If you need to reference Player on game.h to declare a pointer, you can use a forward declaration, like:
class Player;
class game
{
Player *myPlayer;
};