From effedbb3f04e585c42cdab84fa6960ab2c3a3b9c Mon Sep 17 00:00:00 2001 From: NAUD Maxence <maxence.naud@cea.fr> Date: Wed, 9 Aug 2023 13:40:58 +0000 Subject: [PATCH] [Bug] Solve memory leak for complex type parameters serialization Providing a vector as a Parameter for a GenericOperator caused a memory leak. Solved using malloc instead of pointers to vector's data --- include/aidge/utils/CParameter.hpp | 43 +++++++++++++++++------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/include/aidge/utils/CParameter.hpp b/include/aidge/utils/CParameter.hpp index c7d0ea23d..a8f18c03f 100644 --- a/include/aidge/utils/CParameter.hpp +++ b/include/aidge/utils/CParameter.hpp @@ -16,6 +16,7 @@ #include <map> #include <vector> #include <numeric> +#include <cstddef> namespace Aidge { @@ -45,9 +46,9 @@ public: { assert(m_Params.find(i_ParamName) != m_Params.end()); assert(m_Types.find(i_ParamName) != m_Types.end()); - assert(m_Params.at(i_ParamName) <= m_OffSet); + assert(m_Params.at(i_ParamName) <= m_Size); assert(typeid(T).name() == m_Types.at(i_ParamName)); - return *reinterpret_cast<T *>(m_BeginBuffer + m_Params.at(i_ParamName)); + return *reinterpret_cast<T *>(m_Buffer + m_Params.at(i_ParamName)); } ///\brief Add a parameter value, identified by its name @@ -59,12 +60,21 @@ public: /// internal buffer in a new location (previous value is still in memory at its previous location) template<class T> void Add(std::string const &i_ParamName, T const &i_Value) { - m_Buffer.resize(m_Buffer.size() + (sizeof(T) / sizeof(uint8_t))); - m_BeginBuffer = m_Buffer.data(); // Update buffer ptr in case of memory reordering - *reinterpret_cast<T *>(m_BeginBuffer + m_OffSet) - = i_Value; // Black-magic used to add anytype into the vector - m_Params[i_ParamName] = m_OffSet; // Copy pointer offset - m_OffSet += sizeof(T); // Increment offset + const std::size_t addedSize = sizeof(T) / sizeof(std::uint8_t); + std::uint8_t *tmp = m_Buffer; + std::uint8_t *m_NewBuffer = static_cast<std::uint8_t *>(std::malloc((m_Size + addedSize)*sizeof(std::uint8_t))); + + for (std::size_t i = 0; i < m_Size; ++i) { + m_NewBuffer[i] = m_Buffer[i]; + } + free(tmp); + for (std::size_t i = 0; i < addedSize; ++i) { + m_NewBuffer[m_Size+i] = *(reinterpret_cast<const std::uint8_t *>(&i_Value) + i); + } + m_Buffer = m_NewBuffer; + + m_Params[i_ParamName] = m_Size; // Copy pointer offset + m_Size += addedSize; // Increment offset m_Types[i_ParamName] = typeid(i_Value).name(); } @@ -80,10 +90,14 @@ public: } - ~CParameter() = default; + ~CParameter() { + free(m_Buffer); + } private: - // Note for Cyril: of course storing offset and not address! Good idea + /// @brief Number of elements in m_Buffer + std::size_t m_Size = 0; + std::map<std::string, std::size_t> m_Params; // { Param name : offset } ///\brief Map to check type error @@ -95,16 +109,9 @@ private: std::map<std::string, std::string> m_Types; ///\brief All parameters values concatenated in raw binary form. - std::vector<uint8_t> m_Buffer = {}; - - ///\brief Starting address of the buffer - uint8_t *m_BeginBuffer = m_Buffer.data(); - - ///\brief Offset, in number of uint8_t, of the next parameter to write - std::size_t m_OffSet = 0; + std::uint8_t *m_Buffer = static_cast<std::uint8_t *>(std::malloc(0)); }; } - #endif /* __AIDGE_CPARAMETER_H__ */ -- GitLab