1

first question on stackoverflow, was hoping to get some help with this issue. If you take a look at the following EffectManager class, I am getting an assertion failure on _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) when an effectmanager instance is deallocated.

It has something to do with trying to free the memory of the effectsmap, if I never insert the effect into the map I don't run into this problem.

it will also work fine if I use a base STL map, ie

typedef std::map<std::wstring, ID3DXEffect*> EffectsMap;

class EffectManager
{
public:
    typedef boost::ptr_map<std::wstring, ID3DXEffect> EffectsMap;
    EffectManager();
    ~EffectManager();
    void init();
    ID3DXEffect *loadEffect(LPDIRECT3DDEVICE9 d3ddev, std::wstring effectfile);

private:
    std::shared_ptr<EffectsMap> effects_;
};

EffectManager::EffectManager() : effects_(NULL)
{
}

EffectManager::~EffectManager()
{
    for(auto it = effects_->begin(); it != effects_->end(); it++){
        it->second->Release();
    }
}

void EffectManager::init()
{
    effects_ = std::shared_ptr<EffectsMap>(new EffectsMap());
}

ID3DXEffect *EffectManager::loadEffect(LPDIRECT3DDEVICE9 d3ddev, std::wstring effectfile)
{
    if(!effects_)
        return NULL;

    ID3DXEffect *effect;
    if(effects_->count(effectfile)){
        effect = effects_->find(effectfile)->second;
    } else {
        D3DXCreateEffectFromFile(d3ddev, effectfile.c_str(), NULL, NULL, D3DXFX_NOT_CLONEABLE, NULL, &effect, NULL);
        effects_->insert(effectfile, effect);
    }

    return effect;
}
ildjarn
  • 62,044
  • 9
  • 127
  • 211
Faris M
  • 540
  • 4
  • 10
  • 2
    The effect wasn't allocated with new, so you can't delet it. You must use a custom deleted that calls release – Daniel Apr 06 '12 at 20:28
  • Thanks for the comment Dani. How exactly would I go about making a custom deleter that doesn't try to call delete on the effect pointer? I'm also not quite sure exactly when the effects_ goes out of scope as it's stored in a shared_ptr. – Faris M Apr 06 '12 at 20:53
  • @Faris : In the case of `boost::ptr_map<>` I think your only mechanism for supplying a custom deleter is to supply an entire custom allocator, which is certainly non-trivial. Since you're using C++11 already, I think you'd be better off with a `std::map>` or a `std::map>`, since those allow you to specify custom deleters without messing with allocation semantics. – ildjarn Apr 06 '12 at 21:07
  • @ildjarn - Good suggestion. I decided to go with ptr_container implementation due to the advantages listed here http://www.boost.org/doc/libs/1_34_1/libs/ptr_container/doc/ptr_container.html#id23, primarily for exception-safety and smaller memory overhead, but perhaps in scenarios like the EffectManager where the size of the map will be relatively low (no more than 20 effects) it isn't worth it. – Faris M Apr 06 '12 at 21:16
  • @Faris : Those advantages are more or less specific to C++03, and many/most of them are irrelevant in C++11. `std::unique_ptr<>`, for instance, has 0 overhead. – ildjarn Apr 06 '12 at 21:17
  • @ildjarn - Gotcha, sounds like I'll switch to a container of smart pointers then. So are you saying that with c++11 there really is no need for ptr_container anymore? It seems like if I have a collection of objects that were allocated with new, and I don't need a custom deleter, ptr_container can still be useful. – Faris M Apr 06 '12 at 21:22
  • @Faris : The one place ptr_container is still useful is if you need deep copy semantics -- `std::shared_ptr<>` would share ownership of a single object without creating another copy, and `std::unique_ptr<>` is not copyable, only movable. If you _don't_ need deep copy semantics, I would leave ptr_container behind in C++11. – ildjarn Apr 06 '12 at 21:32
  • Why do you use ptr_map? In this case just map does the job. Interface must not be deallocated explicitly, instead it cleans up itself when usage counter reaches 0. I.e. it's enough to release interfaces in destructor to have resources cleaned up. – real4x Apr 08 '12 at 23:16

0 Answers0