In a previous question of mine (see this thread) I was told it was possible to call cache->GetResource(“thingy.xml”)->ReleaseRef();. It appears if you ReleaseRef() a resource after loading and using it, loading another resource of the same type will segfault.
void App::Start()
{
ResourceCache* cache = GetSubsystem<ResourceCache>();
for(int i = 0; i < 10; i++)
{
XMLFile* f = cache->GetResource<XMLFile>("UI/DefaultStyle.xml");
f->GetRoot(); // segfaults for i=1, works at i=0
f->ReleaseRef();
}
}
Another, simpler example even:
void App::Start()
{
ResourceCache* cache = GetSubsystem<ResourceCache>();
for(int i = 0; i < 10; i++)
{
XMLFile* f = cache->GetResource<XMLFile>("UI/DefaultStyle.xml"); // segfaults for i=1, works at i=0
f->ReleaseRef();
}
}
In the first case, GetRoot() fails because document_ is NULL:
[code]XMLElement XMLFile::GetRoot(const String& name)
{
pugi::xml_node root = document_->first_child(); // document_ is NULL.
// SNIP
}[/code]
In the second case, GetResource() fails because refCount_ is pointing to garbage:
[code]void RefCounted::ReleaseRef()
{
assert(refCount_->refs_ > 0); // refCount_ is 0x642f74656d6f002f (this is a garbage value)
// SNIP
}[/code]
After some analysis, the reason is simple: ResourceCache isn’t notified of the resource being destroyed when manually calling ReleaseRef() on it, which means ResourceCache will continue to hold an invalid pointer to the destroyed resource.
So what is the correct way of destroying a resource from the cache manually?