DIRECTOR: Cleanup memory leaks in LingoArchive

Create a variable on ScriptContext to track if it's only in
lctxContexts to ease deletion.

Factories and scripts with script id < 0 are tracked and deleted on
~LingoArchive. The hashmaps lctxContexts and scriptContexts overlap in
the values. The forementioned factories and scripts with script id < 0
were only in lctxContext.
scriptContexts was already cleaned up in ~LingoArchive.
This commit is contained in:
Roland van Laar 2022-09-20 16:09:20 +02:00
parent b517ab6635
commit 43a2e79dec
3 changed files with 19 additions and 0 deletions

View File

@ -1228,6 +1228,10 @@ void Cast::loadLingoContext(Common::SeekableReadStreamEndian &stream) {
error("Cast::loadLingoContext: Script already defined for type %s, id %d", scriptType2str(script->_scriptType), script->_id);
}
_lingoArchive->scriptContexts[script->_scriptType][script->_id] = script;
} else {
// Keep track of scripts that are not in scriptContexts
// Those scripts need to be cleaned up on ~LingoArchive
script->setOnlyInLctxContexts();
}
}
} else {

View File

@ -200,6 +200,9 @@ public:
DatumHash _properties;
Common::HashMap<uint32, Datum> _objArray;
private:
bool _onlyInLctxContexts = false;
public:
ScriptContext(Common::String name, ScriptType type = kNoneScript, int id = 0);
ScriptContext(const ScriptContext &sc);
@ -208,6 +211,9 @@ public:
bool isFactory() const { return _objType == kFactoryObj; };
void setFactory(bool flag) { _objType = flag ? kFactoryObj : kScriptObj; }
void setOnlyInLctxContexts() { _onlyInLctxContexts = true; }
bool getOnlyInLctxContexts() { return _onlyInLctxContexts; }
Common::String asString() override;
Symbol getMethod(const Common::String &methodName) override;
bool hasProp(const Common::String &propName) override;

View File

@ -227,6 +227,15 @@ void Lingo::reloadBuiltIns() {
}
LingoArchive::~LingoArchive() {
// First cleanup the ScriptContexts that are only in LctxContexts.
// LctxContexts has a huge overlap with scriptContexts.
for (ScriptContextHash::iterator it = lctxContexts.begin(); it != lctxContexts.end(); ++it){
ScriptContext *script = it->_value;
if (script->getOnlyInLctxContexts())
delete script;
}
for (int i = 0; i <= kMaxScriptType; i++) {
for (ScriptContextHash::iterator it = scriptContexts[i].begin(); it != scriptContexts[i].end(); ++it) {
*it->_value->_refCount -= 1;