diff --git a/src/module.cpp b/src/module.cpp index 6d6e419..cfb11d7 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -251,6 +251,9 @@ void GoLanguageModule::Shutdown() { _addresses.clear(); _assemblyMap.clear(); _callVirtMachine.reset(); + + DetectLeaks(); + _rt.reset(); _provider.reset(); } @@ -993,7 +996,58 @@ namespace golm { GoLanguageModule g_golm; } -// TODO: Detect leaks +using type_index = uint32_t; +inline type_index type_id_seq = 0; +template inline const type_index type_id = type_id_seq++; + +std::map g_numberOfMalloc = { }; +std::map g_numberOfAllocs = { }; + +std::string_view GetTypeName(type_index type) { + static std::map typeNameMap = { + {type_id, "String"}, + {type_id>, "VectorBool"}, + {type_id>, "VectorChar8"}, + {type_id>, "VectorChar16"}, + {type_id>, "VectorInt8"}, + {type_id>, "VectorInt16"}, + {type_id>, "VectorInt32"}, + {type_id>, "VectorInt64"}, + {type_id>, "VectorUInt8"}, + {type_id>, "VectorUInt16"}, + {type_id>, "VectorUInt32"}, + {type_id>, "VectorUInt64"}, + {type_id>, "VectorUIntPtr"}, + {type_id>, "VectorFloat"}, + {type_id>, "VectorDouble"}, + {type_id>, "VectorString"}, + {type_id, "BoolArray"}, + {type_id, "CString"}, + {type_id, "CStringArray"} + }; + auto it = typeNameMap.find(type); + if (it != typeNameMap.end()) { + return std::get(*it); + } + return "unknown"; +} + +void GoLanguageModule::DetectLeaks() { + for (const auto& [type, count] : g_numberOfMalloc) { + if (count > 0) { + g_golm._provider->Log(std::format(LOG_PREFIX "Memory leaks detected: {} allocations. Related to {}!", count, GetTypeName(type)), Severity::Error); + } + } + + for (const auto& [type, count] : g_numberOfAllocs) { + if (count > 0) { + g_golm._provider->Log(std::format(LOG_PREFIX "Memory leaks detected: {} allocations. Related to {}!", count, GetTypeName(type)), Severity::Error); + } + } + + g_numberOfMalloc.clear(); + g_numberOfAllocs.clear(); +} MemAddr GetMethodPtr(const char* methodName) { return g_golm.GetNativeMethod(methodName); @@ -1008,6 +1062,7 @@ const char* GetBaseDir() { size_t size = source.length() + 1; char* dest = new char[size]; std::memcpy(dest, source.c_str(), size); + g_numberOfAllocs[type_id]++; return dest; } @@ -1054,6 +1109,7 @@ const char* GetPluginBaseDir(PluginRef plugin) { size_t size = source.length() + 1; char* dest = new char[size]; std::memcpy(dest, source.c_str(), size); + g_numberOfAllocs[type_id]++; return dest; } @@ -1063,6 +1119,7 @@ const char** GetPluginDependencies(PluginRef plugin) { for (size_t i = 0; i < dependencies.size(); ++i) { deps[i] = dependencies[i].GetName().data(); } + g_numberOfAllocs[type_id]++; return deps; } @@ -1077,42 +1134,55 @@ const char* FindPluginResource(PluginRef plugin, const char* path) { size_t size = source.length() + 1; char* dest = new char[size]; std::memcpy(dest, source.c_str(), size); + g_numberOfAllocs[type_id]++; return dest; } return ""; } void DeleteCStr(const char* path) { delete path; + g_numberOfAllocs[type_id]--; + assert(g_numberOfAllocs[type_id] != -1); } void* AllocateString() { - return malloc(sizeof(std::string)); + auto str = static_cast(malloc(sizeof(std::string))); + g_numberOfMalloc[type_id]++; + return str; } void* CreateString(GoString source) { - return source.n == 0 ? new std::string() : new std::string(source.p, static_cast(source.n)); + auto str = source.n == 0 || source.p == nullptr ? new std::string() : new std::string(source.p, static_cast(source.n)); + g_numberOfAllocs[type_id]++; + return str; } -const char* GetStringData(std::string* ptr) { - return ptr->c_str(); +const char* GetStringData(std::string* string) { + return string->c_str(); } -ptrdiff_t GetStringLength(std::string* ptr) { - return static_cast(ptr->length()); +ptrdiff_t GetStringLength(std::string* string) { + return static_cast(string->length()); } -void ConstructString(std::string* ptr, GoString source) { - std::construct_at(ptr, std::string(source.p, static_cast(source.n))); +void ConstructString(std::string* string, GoString source) { + if (source.n == 0 || source.p == nullptr) + std::construct_at(string, std::string()); + else + std::construct_at(string, std::string(source.p, static_cast(source.n))); } -void AssignString(std::string* ptr, GoString source) { +void AssignString(std::string* string, GoString source) { if (source.p == nullptr || source.n == 0) - ptr->clear(); + string->clear(); else - ptr->assign(source.p, static_cast(source.n)); + string->assign(source.p, static_cast(source.n)); } -void FreeString(std::string* ptr) { - ptr->~basic_string(); - free(ptr); +void FreeString(std::string* string) { + string->~basic_string(); + free(string); + g_numberOfMalloc[type_id]--; + assert(g_numberOfMalloc[type_id] != -1); } - -void DeleteString(std::string* ptr) { - delete ptr; +void DeleteString(std::string* string) { + delete string; + g_numberOfAllocs[type_id]--; + assert(g_numberOfAllocs[type_id] != -1); } enum DataType { @@ -1133,48 +1203,171 @@ enum DataType { String }; +namespace { + template>> + std::vector* CreateVector(T* arr, ptrdiff_t len) { + auto vector = len == 0 ? new std::vector() : new std::vector(arr, arr + len); + assert(vector); + g_numberOfAllocs[type_id>]++; + return vector; + } + + template>> + std::vector* CreateVector(T* arr, ptrdiff_t len) { + auto vector = new std::vector(); + if (len != 0) { + vector->reserve(static_cast(len)); + for (ptrdiff_t i = 0; i < len; ++i) { + const auto& str = arr[i]; + vector->emplace_back(str.p, str.n); + } + } + assert(vector); + g_numberOfAllocs[type_id>]++; + return vector; + } + + template>> + std::vector* AllocateVector() { + auto vector = static_cast*>(malloc(sizeof(std::vector))); + assert(vector); + g_numberOfMalloc[type_id>]++; + return vector; + } + + template>> + std::vector* AllocateVector() { + auto vector = static_cast*>(malloc(sizeof(std::vector))); + assert(vector); + g_numberOfMalloc[type_id>]++; + return vector; + } + + + template + void DeleteVector(std::vector* vector) { + delete vector; + g_numberOfAllocs[type_id>]--; + assert(g_numberOfAllocs[type_id>] != -1); + } + + template + void FreeVector(std::vector* vector) { + vector->~vector(); + free(vector); + g_numberOfMalloc[type_id>]--; + assert(g_numberOfMalloc[type_id>] != -1); + } + + template + ptrdiff_t GetVectorSize(std::vector* vector) { + return static_cast(vector->size()); + } + + template>> + void AssignVector(std::vector* vector, T* arr, ptrdiff_t len) { + if (arr == nullptr || len == 0) + vector->clear(); + else + vector->assign(arr, arr + len); + } + + template>> + void AssignVector(std::vector* vector, T* arr, ptrdiff_t len) { + if (arr == nullptr || len == 0) + vector->clear(); + else { + size_t N = static_cast(len); + vector->resize(N); + for (size_t i = 0; i < N; ++i) { + const auto& str = arr[i]; + (*vector)[i].assign(str.p, static_cast(str.n)); + } + } + } + + template and !std::is_same_v>> + T* GetVectorData(std::vector* vector) { + return vector->data(); + } + + template>> + bool* GetVectorData(std::vector* vector) { + bool* boolArray = new bool[vector->size()]; + + // Manually copy values from std::vector to the bool array + for (size_t i = 0; i < vector->size(); ++i) { + boolArray[i] = (*vector)[i]; + } + + g_numberOfAllocs[type_id]++; + + return boolArray; + } + + template>> + char** GetVectorData(std::vector* vector) { + char** strArray = new char*[vector->size()]; + + // Manually copy values from std::vector to the char* array + for (size_t i = 0; i < vector->size(); ++i) { + strArray[i] = (*vector)[i].data(); + } + + g_numberOfAllocs[type_id]++; + + return strArray; + } + + template>> + void ConstructVector(std::vector* vector, T* arr, ptrdiff_t len) { + std::construct_at(vector, len == 0 ? std::vector() : std::vector(arr, arr + len)); + } + + template>> + void ConstructVector(std::vector* vector, T* arr, ptrdiff_t len) { + std::construct_at(vector, std::vector()); + size_t N = static_cast(len); + vector->reserve(N); + for (size_t i = 0; i < N; ++i) { + const auto& str = arr[i]; + vector->emplace_back(str.p, static_cast(str.n)); + } + } +} + void* CreateVector(void* arr, ptrdiff_t len, DataType type) { switch (type) { case Bool: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case Char8: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case Char16: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case Int8: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case Int16: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case Int32: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case Int64: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case UInt8: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case UInt16: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case UInt32: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case UInt64: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case Pointer: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case Float: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case Double: - return len == 0 ? new std::vector() : new std::vector(static_cast(arr), static_cast(arr) + len); + return CreateVector(static_cast(arr), len); case String: - { - auto* vector = new std::vector(); - if (len != 0) { - vector->reserve(static_cast(len)); - for (ptrdiff_t i = 0; i < len; ++i) { - const auto& str = static_cast(arr)[i]; - vector->emplace_back(str.p, str.n); - } - } - return vector; - } + return CreateVector(static_cast(arr), len); default: return nullptr; } @@ -1183,35 +1376,35 @@ void* CreateVector(void* arr, ptrdiff_t len, DataType type) { void* AllocateVector(DataType type) { switch (type) { case Bool: - return malloc(sizeof(std::vector)); + return AllocateVector(); case Char8: - return malloc(sizeof(std::vector)); + return AllocateVector(); case Char16: - return malloc(sizeof(std::vector)); + return AllocateVector(); case Int8: - return malloc(sizeof(std::vector)); + return AllocateVector(); case Int16: - return malloc(sizeof(std::vector)); + return AllocateVector(); case Int32: - return malloc(sizeof(std::vector)); + return AllocateVector(); case Int64: - return malloc(sizeof(std::vector)); + return AllocateVector(); case UInt8: - return malloc(sizeof(std::vector)); + return AllocateVector(); case UInt16: - return malloc(sizeof(std::vector)); + return AllocateVector(); case UInt32: - return malloc(sizeof(std::vector)); + return AllocateVector(); case UInt64: - return malloc(sizeof(std::vector)); + return AllocateVector(); case Pointer: - return malloc(sizeof(std::vector)); + return AllocateVector(); case Float: - return malloc(sizeof(std::vector)); + return AllocateVector(); case Double: - return malloc(sizeof(std::vector)); + return AllocateVector(); case String: - return malloc(sizeof(std::vector)); + return AllocateVector(); default: return nullptr; } @@ -1219,36 +1412,36 @@ void* AllocateVector(DataType type) { ptrdiff_t GetVectorSize(void* ptr, DataType type) { switch (type) { - case Bool: - return static_cast(reinterpret_cast*>(ptr)->size()); case Char8: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); case Char16: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); case Int8: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); case Int16: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); case Int32: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); case Int64: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); case UInt8: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); case UInt16: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); case UInt32: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); case UInt64: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); case Pointer: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); case Float: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); case Double: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); + case Bool: + return GetVectorSize(reinterpret_cast*>(ptr)); case String: - return static_cast(reinterpret_cast*>(ptr)->size()); + return GetVectorSize(reinterpret_cast*>(ptr)); default: return -1; // Return -1 or some error code for invalid type } @@ -1256,56 +1449,36 @@ ptrdiff_t GetVectorSize(void* ptr, DataType type) { void* GetVectorData(void* ptr, DataType type) { switch (type) { + case Bool: + return GetVectorData(reinterpret_cast*>(ptr)); case Char8: - return reinterpret_cast*>(ptr)->data(); + return GetVectorData<>(reinterpret_cast*>(ptr)); case Char16: - return reinterpret_cast*>(ptr)->data(); + return GetVectorData<>(reinterpret_cast*>(ptr)); case Int8: - return reinterpret_cast*>(ptr)->data(); + return GetVectorData<>(reinterpret_cast*>(ptr)); case Int16: - return reinterpret_cast*>(ptr)->data(); + return GetVectorData<>(reinterpret_cast*>(ptr)); case Int32: - return reinterpret_cast*>(ptr)->data(); + return GetVectorData<>(reinterpret_cast*>(ptr)); case Int64: - return reinterpret_cast*>(ptr)->data(); + return GetVectorData<>(reinterpret_cast*>(ptr)); case UInt8: - return reinterpret_cast*>(ptr)->data(); + return GetVectorData<>(reinterpret_cast*>(ptr)); case UInt16: - return reinterpret_cast*>(ptr)->data(); + return GetVectorData<>(reinterpret_cast*>(ptr)); case UInt32: - return reinterpret_cast*>(ptr)->data(); + return GetVectorData<>(reinterpret_cast*>(ptr)); case UInt64: - return reinterpret_cast*>(ptr)->data(); + return GetVectorData<>(reinterpret_cast*>(ptr)); case Pointer: - return reinterpret_cast*>(ptr)->data(); + return GetVectorData<>(reinterpret_cast*>(ptr)); case Float: - return reinterpret_cast*>(ptr)->data(); + return GetVectorData<>(reinterpret_cast*>(ptr)); case Double: - return reinterpret_cast*>(ptr)->data(); - case Bool: { - auto& vector = *reinterpret_cast*>(ptr); - - bool* boolArray = new bool[vector.size()]; - - // Manually copy values from std::vector to the bool array - for (size_t i = 0; i < vector.size(); ++i) { - boolArray[i] = vector[i]; - } - - return boolArray; - } - case String: { - auto& vector = *reinterpret_cast*>(ptr); - - char** strArray = new char*[vector.size()]; - - // Manually copy values from std::vector to the char* array - for (size_t i = 0; i < vector.size(); ++i) { - strArray[i] = vector[i].data(); - } - - return strArray; - } + return GetVectorData<>(reinterpret_cast*>(ptr)); + case String: + return GetVectorData(reinterpret_cast*>(ptr)); default: return nullptr; // Return nullptr for invalid type } @@ -1313,87 +1486,51 @@ void* GetVectorData(void* ptr, DataType type) { void ConstructVector(void* ptr, void* arr, ptrdiff_t len, DataType type) { switch (type) { - case Bool: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case Bool: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Char8: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case Char8: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Char16: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case Char16: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Int8: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case Int8: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Int16: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case Int16: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Int32: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case Int32: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Int64: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case Int64: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case UInt8: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case UInt8: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case UInt16: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case UInt16: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case UInt32: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case UInt32: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case UInt64: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case UInt64: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Pointer: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case Pointer: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Float: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case Float: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Double: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, len == 0 ? std::vector() : std::vector(static_cast(arr), static_cast(arr) + len)); + case Double: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case String: { - auto* vector = reinterpret_cast*>(ptr); - std::construct_at(vector, std::vector()); - size_t N = static_cast(len); - vector->reserve(N); - for (size_t i = 0; i < N; ++i) { - const auto& str = static_cast(arr)[i]; - vector->emplace_back(str.p, static_cast(str.n)); - } + case String: + ConstructVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } default: break; } @@ -1401,132 +1538,51 @@ void ConstructVector(void* ptr, void* arr, ptrdiff_t len, DataType type) { void AssignVector(void* ptr, void* arr, ptrdiff_t len, DataType type) { switch (type) { - case Bool: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case Bool: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Char8: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case Char8: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Char16: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case Char16: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Int8: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case Int8: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Int16: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case Int16: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Int32: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case Int32: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Int64: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case Int64: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case UInt8: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case UInt8: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case UInt16: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case UInt16: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case UInt32: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case UInt32: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case UInt64: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case UInt64: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Pointer: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case Pointer: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Float: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case Float: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case Double: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else - vector->assign(static_cast(arr), static_cast(arr) + len); + case Double: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } - case String: { - auto* vector = reinterpret_cast*>(ptr); - if (arr == nullptr || len == 0) - vector->clear(); - else { - size_t N = static_cast(len); - vector->resize(N); - for (size_t i = 0; i < N; ++i) { - const auto& str = static_cast(arr)[i]; - (*vector)[i].assign(str.p, static_cast(str.n)); - } - } + case String: + AssignVector(reinterpret_cast*>(ptr), static_cast(arr), len); break; - } default: break; } @@ -1535,49 +1591,49 @@ void AssignVector(void* ptr, void* arr, ptrdiff_t len, DataType type) { void DeleteVector(void* ptr, DataType type) { switch (type) { case Bool: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case Char8: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case Char16: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case Int8: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case Int16: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case Int32: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case Int64: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case UInt8: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case UInt16: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case UInt32: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case UInt64: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case Pointer: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case Float: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case Double: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; case String: - delete reinterpret_cast*>(ptr); + DeleteVector(reinterpret_cast*>(ptr)); break; default: // Invalid type, do nothing or handle error if needed @@ -1588,63 +1644,66 @@ void DeleteVector(void* ptr, DataType type) { void FreeVector(void* ptr, DataType type) { switch (type) { case Bool: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case Char8: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case Char16: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case Int8: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case Int16: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case Int32: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case Int64: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case UInt8: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case UInt16: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case UInt32: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case UInt64: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case Pointer: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case Float: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case Double: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; case String: - reinterpret_cast*>(ptr)->~vector(); + FreeVector(reinterpret_cast*>(ptr)); break; default: // Invalid type, do nothing or handle error if needed return; } - free(ptr); } void DeleteVectorDataBool(void* ptr) { delete[] reinterpret_cast(ptr); + g_numberOfAllocs[type_id]--; + assert(g_numberOfAllocs[type_id] != -1); } void DeleteVectorDataCStr(void* ptr) { delete[] reinterpret_cast(ptr); + g_numberOfAllocs[type_id]--; + assert(g_numberOfAllocs[type_id] != -1); } const std::array GoLanguageModule::_pluginApi = { diff --git a/src/module.h b/src/module.h index 5112335..03fa9bd 100644 --- a/src/module.h +++ b/src/module.h @@ -96,6 +96,7 @@ namespace golm { private: static void InternalCall(plugify::MethodRef method, plugify::MemAddr data, const plugify::Parameters* params, uint8_t count, const plugify::ReturnValue* ret); + static void DetectLeaks(); private: std::shared_ptr _rt;