-1
\$\begingroup\$

firstly iam used to java and new to c++ so maybe this will looks a noob's question i will explain this and give a pseudo code and then c++ just so you can understand me

i have a player class which inherit from gameobject and a handler class which update all the game objects(stored in vector) and render them i have a function to add objects but i get errors every time (i work with SDL2 if this gonna help)

pseudo code:

///some class
handler hand = new handler();
gameObject pla = new player();
hand.addObject(pla);  ----> here

/// handler class 

vector<gameObject> objects;

void addObjects(gameObject object) 
{
   objects.push(object);  ------> specially here
}

C++ code

/// game class

handler hand = new handler();
gameobject* pla = new player();
hand->addobject(pla); 

/// handler class

vector<gameobject*> objects;

void addobject(gameobject* object)
{
    objects.push_back(object); -----> here
}

i have searched for a week and nothing i used unique_ptr but nothing every time new error some times std::bad_alloc sometimes objects has been deleted

i am confused please guide me to the right way to do this

thank you

\$\endgroup\$
1
\$\begingroup\$

Your crashes is mostly because of improper handling of the object's ownership.

When you add something to a collection, you should clearly understand who's owning the object. Is that handler owns the added objects now, and may delete those when time has come? Or is that handler only references the objects, and there's some other subsystem that will destroy the objects? Get clear with ownership first, because implementation will differ.

Assigning unique_ptr to a collection assumes ownership is transferred to that collection. There's no other way to push_back the unique_ptr into a vector. There can't be multiple copies of the same unique_ptr. Well, technically you could construct multiple unique_ptr from the very same raw pointer, but that's a big no-no.

In case your handler will own the objects, the next example is possible:

#include <vector>
#include <memory>

using std::vector;
using std::unique_ptr;
using std::move;

/// gameobjec base class
class gameobject
{
public:
    virtual ~gameobject() {};
};

/// player class
class player: public gameobject
{
public:
    float* some_data;

    player(int map_size)
    {
        some_data = new float[map_size];
    }

    ~player()
    {
        delete[] some_data;
    }
};

/// handler class
class handler
{
public:
    vector<gameobject*> objects;
    vector<unique_ptr<gameobject> > objects_auto;

    void addobject(gameobject* object)
    {
        objects.push_back(object);
    }


    void addobject(unique_ptr<gameobject>& object)
    {
        objects_auto.push_back(move(object));
    }

    void add_raw_to_auto(gameobject* object)
    {
        objects_auto.push_back(unique_ptr<gameobject>(object));
    }

    ~handler()
    {
        // objects behind raw pointers must be explicitly deleted
        for(auto obj: objects)
            delete obj;

        // nothing needs to be done about unique_ptr containers
    }
};

int main()
{
    handler* hand = new handler();

    for(int i=0; i<100; ++i)
    {
        // add raw pointer to a collection of raw pointers
        gameobject* pla = new player(i);
        hand->addobject(pla);

        // add unique_ptr to a collection of unique_ptr
        unique_ptr<gameobject> pla_auto(new player(i*2));
        hand->addobject(pla_auto);

        // add raw pointer to a collection of unique ptr
        gameobject* pla_raw = new player(i);
        hand->add_raw_to_auto(pla_raw);
    }

    delete hand;
}

Since in handler you're storing the pointer to a base class, you should make virtual destructor there, so the collections of pointers to different objects inherited from that base class will be properly destroyed. A memory leaks are possible if the base class' destructor isn't virtual.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ but the first addobject method don't work i tried it and it say what():std::_bad_alloc \$\endgroup\$ – younlok Dec 2 '19 at 8:32
  • \$\begingroup\$ @younlok The crash is likely in the code you didn't show. This example works ok: ideone.com/StLMx2 and passes the Valgrind checks. \$\endgroup\$ – Vlad Dec 2 '19 at 8:41
  • \$\begingroup\$ maybe the class is small that's why it works but i have problem with this that why i was confused and i showed all the code that has relation to the problem \$\endgroup\$ – younlok Dec 2 '19 at 8:44
  • \$\begingroup\$ and i read that if its more than one file this will also cause a problem \$\endgroup\$ – younlok Dec 2 '19 at 8:45
  • \$\begingroup\$ @younlok The class size isn't important, unless there's gigabytes of arrays inside. Every program is built from many files, it's not a factor here too, unless you only recompile one file ignoring dependencies. You showed the spot which triggers the bug, but it's not the spot that's causes the bug. Try to build a minimal program that reproduces the crash. Run it under Valgrind and see the exact trace to the spot where it crashes, then you could find the real cause. \$\endgroup\$ – Vlad Dec 2 '19 at 9:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.