From 6c6d977000fffaef1e1d9d029cf3ebeb8411da18 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Thu, 19 Sep 2019 11:02:59 +0200 Subject: [PATCH] Union with shared_ptr caused a memory leak. Prevent this using std::variant --- src/ScriptTypes/TableScriptType.hpp | 49 ++++++++++++++++++----------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/ScriptTypes/TableScriptType.hpp b/src/ScriptTypes/TableScriptType.hpp index 5293cb3..4e32e71 100644 --- a/src/ScriptTypes/TableScriptType.hpp +++ b/src/ScriptTypes/TableScriptType.hpp @@ -16,14 +16,25 @@ namespace Porygon{ Dictionary }; - bool _isContentAware; + using ContentTypes = unordered_map>*; + using KeyValueType = std::pair, shared_ptr>; + + bool _isContentAware = false; TableType _tableType; - union{ - shared_ptr _valueType; // numerical - unordered_map>* _contentTypes = nullptr; // string keyed - std::pair, shared_ptr> _keyValueType; // dictionary - }; + std::variant< + shared_ptr, + ContentTypes, + KeyValueType + > _valueType, _contentTypes, _keyValueType; + + [[nodiscard]] inline shared_ptr GetValueType() const{ + return std::get>(_valueType); + } + + [[nodiscard]] inline KeyValueType GetKeyValueTypes() const{ + return std::get(_keyValueType); + } public: explicit TableScriptType() @@ -41,7 +52,7 @@ namespace Porygon{ ~TableScriptType() override { if (_tableType == TableType::StringKeyed) - delete _contentTypes; + delete GetContentTypes(); } [[nodiscard]] bool CanBeIterated() const final { @@ -71,7 +82,7 @@ namespace Porygon{ return indexer->GetClass() == TypeClass::Number; } else{ - auto keyType = _keyValueType.first; + auto keyType = GetKeyValueTypes().first; return indexer->CastableTo(keyType, false) != CastResult ::InvalidCast; } } @@ -89,25 +100,25 @@ namespace Porygon{ auto stringType = dynamic_pointer_cast(indexer); if (stringType->IsKnownAtBind() && _isContentAware){ auto h = stringType->GetHashValue(); - return _contentTypes->at(h); + return GetContentTypes()->at(h); } return ScriptType::AnyType; } else if (_tableType == TableType::Numerical){ - return _valueType; + return GetValueType(); } else{ - return _keyValueType.second; + return GetKeyValueTypes().second; } } [[nodiscard]] shared_ptr GetIndexedType(uint32_t hash) const override { auto lookup = Utilities::HashedString::CreateLookup(hash); - return _contentTypes->at(lookup); + return GetContentTypes()->at(lookup); } - unordered_map>* GetContentTypes() const{ - return _contentTypes; + [[nodiscard]] inline ContentTypes GetContentTypes() const{ + return std::get(_contentTypes); } [[nodiscard]] @@ -117,12 +128,12 @@ namespace Porygon{ case Unknown: return true; case Numerical: return indexer->GetClass() == TypeClass ::Number && - val->CastableTo(_valueType, false) != CastResult ::InvalidCast; + val->CastableTo(GetValueType(), false) != CastResult ::InvalidCast; case StringKeyed: return indexer->GetClass() == TypeClass ::String; case Dictionary: - return indexer->CastableTo(_keyValueType.first, false) != CastResult ::InvalidCast && - val->CastableTo(_keyValueType.second, false) != CastResult ::InvalidCast; + return indexer->CastableTo(GetKeyValueTypes().first, false) != CastResult ::InvalidCast && + val->CastableTo(GetKeyValueTypes().second, false) != CastResult ::InvalidCast; } } @@ -144,14 +155,14 @@ namespace Porygon{ auto s = dynamic_pointer_cast(indexer); if (s->IsKnownAtBind()){ auto key = s->GetHashValue(); - _contentTypes->insert({key, val}); + GetContentTypes()->insert({key, val}); } } } void SetIndexValue(Utilities::HashedString indexer, shared_ptr val) const override { if (_tableType == TableType::StringKeyed){ - _contentTypes->insert({indexer, val}); + GetContentTypes()->insert({indexer, val}); } else if (_tableType == TableType::Unknown){ auto t = const_cast(this);