Alright so I've been struggling to find the error but I simply can't. Given the following code:

#include <iostream>
#include <vector>

enum ScriptType
{
    SCRIPT_TYPE_CREATURE_SCRIPT,
    SCRIPT_TYPE_PLAYER_SCRIPT
};

class Script
{
private:
    ScriptType type;
public:
    Script(ScriptType type) : type(type)
    {
    }

    ScriptType getScriptType() const
    {
        return type;
    }
};

class CreatureScript : public Script
{
public:
    CreatureScript() : Script(SCRIPT_TYPE_CREATURE_SCRIPT)
    {
    }

    virtual void OnDealDamage() { }
    virtual void OnKill() { }
};

class PlayerScript : public Script
{
public:
    PlayerScript() : Script(SCRIPT_TYPE_PLAYER_SCRIPT)
    {
    }

    virtual void OnSay() { }
};

class ScriptFactory
{
private:
    static std::vector<Script *> scripts;
public:
    static void Register(Script *s);
    static void Unregister();

    static std::vector<Script *> getScriptsByType(ScriptType type);
};

std::vector<Script *> ScriptFactory::scripts;

void ScriptFactory::Register(Script *s)
{
    scripts.push_back(s);
    std::cout << "Pushed at address: " << s << std::endl;
}

void ScriptFactory::Unregister()
{
    std::vector<Script *>::iterator iter = scripts.begin();
    for (iter; iter != scripts.end(); ++iter)
    {
        std::cout << "Trying to free memory at: " << *iter << std::endl;
        delete *iter;
    }

    scripts.clear();
}

std::vector<Script *> ScriptFactory::getScriptsByType(ScriptType type)
{
    std::vector<Script *>::iterator iter = scripts.begin();
    std::vector<Script *> values;
    for (iter; iter != scripts.end(); ++iter)
        if ((*iter)->getScriptType() == type)
            values.push_back(*iter);

    return values;
}

class CreatureScriptTest : public CreatureScript
{
public:
    CreatureScriptTest() : CreatureScript()
    {
    }

    void OnDealDamage()
    {
        std::cout << "OnDealDamage() called from CreatureScriptTest." << std::endl;
    }
};

class CreatureScriptTest2 : public CreatureScript
{
public:
    CreatureScriptTest2() : CreatureScript()
    {
    }

    void OnDealDamage()
    {
        std::cout << "OnDealDamage() called from CreatureScriptTest2." << std::endl;
    }
};

class PlayerScriptTest : public PlayerScript
{
public:
    PlayerScriptTest() : PlayerScript()
    {
    }

    void OnSay()
    {
        std::cout << "OnSay() called from PlayerScriptTest." << std::endl;
    }
};

class ScriptMgr
{
    typedef std::vector<Script *> ScriptStorage;
#define ITERATE(container, type) \
    ScriptStorage scripts = ScriptFactory::getScriptsByType(type); \
    for (ScriptStorage::iterator itr = container.begin(); itr != container.end(); ++itr)
public:
    static void OnCreatureDealDamage()
    {
        ITERATE(scripts, SCRIPT_TYPE_CREATURE_SCRIPT)
            static_cast<CreatureScript *>(*itr)->OnDealDamage();
    }

    static void OnCreatureKill()
    {
        ITERATE(scripts, SCRIPT_TYPE_CREATURE_SCRIPT)
            static_cast<CreatureScript *>(*itr)->OnKill();
    }

    static void OnPlayerSay()
    {
        ITERATE(scripts, SCRIPT_TYPE_PLAYER_SCRIPT)
            static_cast<PlayerScript *>(*itr)->OnSay();
    }
};

int main()
{
    ScriptFactory::Register(new CreatureScriptTest());
    ScriptFactory::Register(new CreatureScriptTest2());
    ScriptFactory::Register(new PlayerScriptTest());
    ScriptMgr::OnCreatureDealDamage();
    ScriptMgr::OnPlayerSay();

    ScriptFactory::Unregister();

    return 0;
}

It gives the correct output and everything seems to be working fine, except that I get a runtime error on ScriptFactory::Unregister() at line 71: delete *iter;
Using MSVC 2010 I get the following on running in Debug mode:
Click Here
So I see that the program is trying to free a valid memory address which was previously allocated using new. But I still get that error telling me that the pointer is invalid.

Umm, no I'm not? I dereference the iterator *iter, so wouldn't that return a pointer to a Script object?

Indeed, I've added a virtual destructor to Script class and it worked. Thank you!

This article has been dead for over six months. Start a new discussion instead.