1
\$\begingroup\$

I do not know if this is the best way to handle these SDL_Events, but I am attempting to create a very abstract and generic code that will update my game object. I have a Scene which in my case is just a map from a string to a game object that has special functions to Add(string key, gameobject value), Remove(string key), Render(), and Update(SDL_Event& event). I think this last method is the problem.

Scene.cpp

void Scene::Update(SDL_Event& ev)
{
    for (std::map<std::string, GameObject&>::iterator it = x_ObjectDictionary.begin(); it != x_ObjectDictionary.end(); ++it)
    {
        it->second.Update(ev); //where the game crashes
    }
}

void Scene::Render()
{
    for (std::map<std::string, GameObject&>::iterator it = x_ObjectDictionary.begin(); it != x_ObjectDictionary.end(); ++it)
    {
        it->second.Render();
    }
}

void Scene::Add(const std::string& key, GameObject& value)
{
    x_ObjectDictionary.insert(std::pair<std::string, GameObject&>(key, value));
}

GameObject& Scene::Get(const std::string& key)
{
    std::map<std::string, GameObject&>::const_iterator iterator = x_ObjectDictionary.find(key);
    if (iterator == x_ObjectDictionary.end()) return GameObject();
    return iterator->second;
}

GameObject& Scene::Remove(const std::string& key)
{
    GameObject removed;
    std::map<std::string, GameObject&>::const_iterator iterator = x_ObjectDictionary.find(key);
    if (iterator == x_ObjectDictionary.end()) return GameObject();
    removed = iterator->second;
    x_ObjectDictionary.erase(iterator);
    return removed;
}

This iterates my map and updates all of the GameObjects. My game object update method is defined like this in the header file:

GameObject.h

class GameObject
{
public:
    GameObject() {}
    virtual ~GameObject() {}

    virtual void Update(SDL_Event& ev){}

    virtual void Render(){}

    virtual void Destroy(){}

};

Now, I created a scene. This Scene is called Splash and extends Scene properly. I created it like so

void Splash::CreateScene()
{
    Add("something", GameObject());
}

Every time I execute/debug my project now, my program "breaks" on the it->second.Update(ev); line and inside the console after I stop "debugging" the message says something along the lines of Exception thrown at 0x00007FF7CB457024 in XXXXXX.exe: 0xC0000005: Access violation reading location 0x00001CFA67BC13F9.

Am I going about this completely incorrectly? Or did I just make a stupid mistake?

\$\endgroup\$
  • \$\begingroup\$ can you provide your Add and Remove methods? \$\endgroup\$ – alariq Jul 7 '15 at 9:21
  • \$\begingroup\$ yes, I aslo added some others just to make more sence. @alariq \$\endgroup\$ – Thomas Steinholz Jul 7 '15 at 17:06
1
\$\begingroup\$

Looks like you have some problems with references.

Strictly saying, you cannot return local object as a reference, nor you can bind non-const reference to a temp object like this:

Add("something", GameObject()); 

I wonder how did you get it to compile... If you want to remove references be sure that they are not destroyed (e.g. by goingout of scope). E.g. next code will not behave correctly:

if(some_condition==true)
{
    GameObject go1;
    scene.Add("a", go1);
}
scene.Update(); // possible crash or garbage, because go1 does not exist there.

Also both Get and Remove functions have errors. You cannot return references to local objects.

GameObject& Scene::Remove(const std::string& key)
{
    GameObject removed;
    std::map<std::string, GameObject&>::const_iterator iterator =    
        x_ObjectDictionary.find(key);
    if (iterator == x_ObjectDictionary.end()) return GameObject(); // cannot return local object!
    removed = iterator->second;
    x_ObjectDictionary.erase(iterator);
    return removed; // cannot return local object!
}

You can either work with pointers, but make sure that they were correctly allocated/destroyed. This way your Get and Remove method will be simpler. You can just return nullptr/NULL/0 instead of constructing and returning dummy object. If you do not want to use pointers than you can have dummy static object inside your scene class and return it. But you still need to make sure that your ordinary objects are not going out of scope.

As an example, Get/Remove could look like this:

      const GameObject& Get(const std::string& key)
      {
              std::map<std::string, GameObject&>::const_iterator iterator = x_ObjectDictionary.find(key);
              if (iterator == x_ObjectDictionary.end()) return s_GO;
              return iterator->second;
      }

      // note: returned object is not a reference!
      GameObject Remove(const std::string& key)
      {
              GameObject removed("");
              std::map<std::string, GameObject&>::iterator iterator = x_ObjectDictionary.find(key);
              if (iterator == x_ObjectDictionary.end()) return GameObject();
              removed = iterator->second;
              x_ObjectDictionary.erase(iterator);
              return removed;
      }

where s_GO is a static member in Scene class.

Hope this helps.

\$\endgroup\$
0
\$\begingroup\$

It seems that you have used different types in it->second.Update(ev) (ev - SDL_Event&). And in it second type is GameObject&.

\$\endgroup\$
  • \$\begingroup\$ I am calling Update(SDL_Event& ev) from the Game Object class. I don't understand what you mean by using the wrong type, because I am passing in an SDL_Event in the param, in which it takes. \$\endgroup\$ – Thomas Steinholz Jul 7 '15 at 8:20
  • \$\begingroup\$ Try to pass a pointer to GameObject instead of reference and test if SDL_Event is passed correctly to GameObject.h. \$\endgroup\$ – Atlantic-sys Jul 8 '15 at 10:03

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.