From d4ee19c6af30440062cfb0d168ad899573ae07da Mon Sep 17 00:00:00 2001 From: VDm Date: Sun, 17 Aug 2025 16:30:57 +0400 Subject: [PATCH] feat(memory): add assertion mode check to CDataAllocator --- .gitignore | 6 ++++- common/memory/CDataAllocator.cpp | 11 ++++++--- common/memory/CDataAllocator.hpp | 24 ++++++++++++++++++++ test/DataAllocator.cpp | 39 ++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 test/DataAllocator.cpp diff --git a/.gitignore b/.gitignore index c00a275..9bd1c02 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ .DS_Store -.idea +.vs .vscode +.idea /build /cmake-build-* +/out + +/CMakeSettings.json diff --git a/common/memory/CDataAllocator.cpp b/common/memory/CDataAllocator.cpp index 645b9c8..45f210d 100644 --- a/common/memory/CDataAllocator.cpp +++ b/common/memory/CDataAllocator.cpp @@ -11,9 +11,13 @@ CDataAllocator::CDataAllocator(uint32_t bytesPerData, uint32_t dataPerBlock) { } CDataAllocator::~CDataAllocator() { + if (this->m_blockList) { + Clear(__FILE__, __LINE__); + } } void CDataAllocator::Clear(const char* fileName, int32_t lineNumber) { +#if defined(WHOA_BUILD_ASSERTIONS) if (this->m_dataUsed) { if (!fileName) { fileName == __FILE__; @@ -21,7 +25,7 @@ void CDataAllocator::Clear(const char* fileName, int32_t lineNumber) { } SErrDisplayErrorFmt( - 0x8510007E, + STORM_ERROR(0x7E), fileName, lineNumber, 1, @@ -34,6 +38,7 @@ void CDataAllocator::Clear(const char* fileName, int32_t lineNumber) { this->m_dataPerBlock, this->m_bytesPerData); } +#endif while (this->m_blockList) { auto block = this->m_blockList; @@ -63,7 +68,7 @@ CDataAllocator::Data* CDataAllocator::GetData(int32_t zero, const char* fileName lineNumber, 0)); Block* block = reinterpret_cast(memory); - Data* data = reinterpret_cast(memory + sizeof(Block*)); + Data* data = reinterpret_cast(memory + sizeof(Block)); this->m_dataList = data; for (uint32_t i = 0; i < this->m_dataPerBlock - 1; ++i) { @@ -71,7 +76,7 @@ CDataAllocator::Data* CDataAllocator::GetData(int32_t zero, const char* fileName data->m_next = reinterpret_cast(next); data = data->m_next; } - data->m_next = 0; + data->m_next = nullptr; block->m_next = this->m_blockList; this->m_blockList = block; } diff --git a/common/memory/CDataAllocator.hpp b/common/memory/CDataAllocator.hpp index 7ae1641..44fbf39 100644 --- a/common/memory/CDataAllocator.hpp +++ b/common/memory/CDataAllocator.hpp @@ -2,6 +2,25 @@ #define COMMON_MEMORY_C_DATA_ALLOCATOR_HPP #include +#include +#include +#include + +#define ALLOCATOR_GET(allocator) allocator.GetData(0, __FILE__, __LINE__) +#define ALLOCATOR_GET_ZERO(allocator) allocator.GetData(1, __FILE__, __LINE__) +#define ALLOCATOR_NEW(allocator, T, ...) (new (allocator.GetData(0, __FILE__, __LINE__)) T(__VA_ARGS__)) +#define ALLOCATOR_NEW_ZERO(allocator, T, ...) (new (allocator.GetData(1, __FILE__, __LINE__)) T(__VA_ARGS__)) + +#define ALLOCATOR_PUT(allocator, ptr) allocator.PutData(ptr, __FILE__, __LINE__) +#define ALLOCATOR_PUT(allocator, ptr) \ + do { \ + if (ptr) { \ + using __data_object = std::remove_pointer::type>::type; \ + (ptr)->~__data_object(); \ + allocator.PutData(ptr, __FILE__, __LINE__); \ + } \ + } while (0) + class CDataAllocator { public: @@ -21,6 +40,11 @@ class CDataAllocator { Data* GetData(int32_t zero, const char* fileName, int32_t lineNumber); void PutData(void* data, const char* fileName, int32_t lineNumber); + inline uint32_t BytesPerData() const { return this->m_bytesPerData; } + inline uint32_t DataPerBlock() const { return this->m_dataPerBlock; } + inline uint32_t DataUsed() const { return this->m_dataUsed; } + + private: // Member variables uint32_t m_bytesPerData = sizeof(Data); uint32_t m_dataPerBlock = 1; diff --git a/test/DataAllocator.cpp b/test/DataAllocator.cpp new file mode 100644 index 0000000..b957bcb --- /dev/null +++ b/test/DataAllocator.cpp @@ -0,0 +1,39 @@ +#include "common/DataAllocator.hpp" +#include "test/Test.hpp" + +struct TestContainer +{ + uint32_t value[10]; +}; + +TEST_CASE("CDataAllocator::CDataAllocator", "[dataallocator]") { + SECTION("constructs new data allocator") { + CDataAllocator allocator(sizeof(TestContainer), 2); + SUCCEED(); + } +} + +TEST_CASE("CDataAllocator::GetData", "[dataallocator]") { + SECTION("get allocated objects") { + CDataAllocator allocator(sizeof(TestContainer), 2); + auto container = (TestContainer*)allocator.GetData(0, __FILE__, __LINE__); + auto container2 = (TestContainer*)allocator.GetData(0, __FILE__, __LINE__); + auto container3 = (TestContainer*)allocator.GetData(0, __FILE__, __LINE__); + REQUIRE(container); + REQUIRE(container2); + REQUIRE(container3); + REQUIRE(allocator.DataUsed() == 3); + } +} + +TEST_CASE("CDataAllocator::PutData", "[dataallocator]") { + SECTION("return allocated objects") { + CDataAllocator allocator(sizeof(TestContainer), 2); + auto container = (TestContainer*)allocator.GetData(0, __FILE__, __LINE__); + auto container2 = (TestContainer*)allocator.GetData(0, __FILE__, __LINE__); + auto container3 = (TestContainer*)allocator.GetData(0, __FILE__, __LINE__); + allocator.PutData(container, __FILE__, __LINE__); + allocator.PutData(container3, __FILE__, __LINE__); + REQUIRE(allocator.DataUsed() == 1); + } +}