简体   繁体   中英

Possibility of a pointer memory leak?

I have a basic Game class written in c++, and a Character class which takes a pointer to the game as an argument for its constructor. I am fairly new to all of this newfangled "C++" and "pointer" jazz, so please bear with me if this seems like a noobish question. The actual code has much more to it, but for demonstration purposes I have compressed it down a bit:

class Game {
  Game() { /* blah blah blah */ };
  ~Game() {};
};
class Character {
  Character(Game *game, unsigned int x, unsigned int y) {
    /* here there be dragons */
  };
  ~Character() {} // empty destructor
};

My question is, do I need to delete the pointer to the main Game instance after I'm done with any given Character, or is the pointer completely unaffiliated with memory leaks? I have 800+ characters in one game at any given point in time, so if the pointer were to cause a memory leak there would be a bit of an issue.

My question is, do I need to delete the pointer to the main Game instance after I'm done with any given Character

Not necessarily.

The pointed Game instance should be destroyed as should all objects sure, but should a Character instance be responsible for that?

You say that there will be many character instances. Consider: Will there be many game instances as well? Do each character point to their own game object?


If each character has their own separate game then it indeed does make sense for the character to be responsible for the destruction of their game. In that case, it might make li ttle sense to use pointers, as it would be simpler to use a direct subobject.

But if many characters refer to a shared game (which I suspect is the case), then a single character can't have sole ownership of that game, because as soon as any one character is destroyed, the others would still be pointing to that game.


Here are two approaches to shared ownership

  1. Use a game instance that has longer lifetime than any of the character instances. For example, a static object, or an automatic object in the main function. That way no character is responsible for the destruction. The tricky part is to make sure that all character instances are destroyed before the game is.

  2. Use a reference counting smart pointer such as std::shared_ptr . This way the game is destroyed when the last character is.

Since you initialize the Game object dynamically, it will not be destroyed until you explicitly do so. So yes, at one point of time, you will need to destroy the Game object if you used pointers and dynamic allocation.

You can test this in the following manner:

#include <iostream>
class Game {
public:
    Game() 
    {
        std::cout << "Game Object Initialized\n";
    }
    ~Game()
    {
        std::cout << "Game object destroyed\n";
    }
};
class Character {
    Game *g;
public:
    Character(Game *game, unsigned int x, unsigned int y) {
        g = game;
        std::cout << "Character Object Initialized\n";
    }
    ~Character()
    {
        std::cout << "Character Object Destroyed\n";
    }
};

void main()
{
    Game *gameObj = new Game();
    Character *characterObj = new Character(gameObj, 0, 0);
    delete characterObj;

}

Output:

Game Object Initialized

Character Object Initialized

Character Object Destroyed

In this case gameObj is still accesible after characterObj is destroyed. You can pass this object to new Characters. Of course, it needs to be destroyed with delete gameObj; .


If you want the Game object to be destroyed automatically when all characters are deallocated: as others have mentioned, you can use a shared_ptr object instead.

#include <iostream>
#include <memory>

class Game {
public:
    Game()
    {
        std::cout << "Game Object Initialized\n";
    }
    ~Game()
    {
        std::cout << "Game object destroyed\n";
    }
};
class Character {
    std::shared_ptr<Game> g;
public:
    Character(std::shared_ptr<Game> game, unsigned int x, unsigned int y)
    {
        g = game;
        std::cout << "Character Object Initialized\n";
    }
    ~Character()
    {
        std::cout << "Character Object Destroyed\n";
    }
};

void main()
{
    //to instantiate a shared_ptr, pass pointer to game as argument in constructor
    std::shared_ptr<Game> gameObj(new Game()); 
    Character *characterObj_0 = new Character(gameObj, 0, 0);
    Character *characterObj_1 = new Character(gameObj, 0, 0);

    delete characterObj_0;
    delete characterObj_1;

    Character *characterObj_2 = new Character(gameObj, 0, 0);

    delete characterObj_2;
}

Game Object Initialized

Character Object Initialized

Character Object Initialized

Character Object Destroyed

Character Object Destroyed

Character Object Initialized

Character Object Destroyed

Game object destroyed

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM