diff --git a/src/Base/PreCompiled.h b/src/Base/PreCompiled.h index 33b7e46f87..8debb1c881 100644 --- a/src/Base/PreCompiled.h +++ b/src/Base/PreCompiled.h @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +83,7 @@ #include // Xerces +#include #include #include #include @@ -95,6 +97,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Base/XMLTools.cpp b/src/Base/XMLTools.cpp index 7b6c911c99..60ac09ae12 100644 --- a/src/Base/XMLTools.cpp +++ b/src/Base/XMLTools.cpp @@ -23,6 +23,11 @@ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#include +#endif + #include "Exception.h" #include "XMLTools.h" @@ -128,3 +133,19 @@ void XMLTools::terminate() { transcoder.reset(); } + +void* XStrMemoryManager::allocate(XMLSize_t size) +{ + auto ptr = ::operator new(static_cast(size), + static_cast(alignof(XMLCh)), + std::nothrow); + if (ptr == nullptr && size != 0) { + throw XERCES_CPP_NAMESPACE::OutOfMemoryException(); + } + return ptr; +} + +void XStrMemoryManager::deallocate(void* p) +{ + ::operator delete(p); +} diff --git a/src/Base/XMLTools.h b/src/Base/XMLTools.h index 5ef0799bb3..d9526ddcc0 100644 --- a/src/Base/XMLTools.h +++ b/src/Base/XMLTools.h @@ -28,6 +28,7 @@ #include #include #include +#include #ifndef XERCES_CPP_NAMESPACE_BEGIN #define XERCES_CPP_NAMESPACE_QUALIFIER @@ -58,6 +59,23 @@ private: static std::unique_ptr transcoder; // NOLINT }; +// Helper class for XStrLiteral macro +// This implementation is almost same as Xerces default memory manager. +class BaseExport XStrMemoryManager final: public XERCES_CPP_NAMESPACE::MemoryManager +{ +public: + XStrMemoryManager() = default; + ~XStrMemoryManager() = default; + + MemoryManager* getExceptionMemoryManager() override + { + return this; + } + + void* allocate(XMLSize_t size) override; + void deallocate(void* p) override; +}; + //************************************************************************** //************************************************************************** // StrXLocal @@ -149,6 +167,8 @@ class XStr public: /// Constructors and Destructor explicit XStr(const char* const toTranscode); + explicit XStr(const char* const toTranscode, + XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* memMgr); ~XStr(); @@ -159,24 +179,35 @@ public: private: /// This is the Unicode XMLCh format of the string. XMLCh* fUnicodeForm; + XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* memMgr; }; inline XStr::XStr(const char* const toTranscode) - : fUnicodeForm(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(toTranscode)) + : XStr(toTranscode, XERCES_CPP_NAMESPACE_QUALIFIER XMLPlatformUtils::fgMemoryManager) +{} + +inline XStr::XStr(const char* const toTranscode, + XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager* memMgr) + : fUnicodeForm(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(toTranscode, memMgr)) + , memMgr(memMgr) {} inline XStr::~XStr() { - XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&fUnicodeForm); + XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&fUnicodeForm, memMgr); } // Uses the compiler to create a cache of transcoded string literals so that each subsequent call // can reuse the data from the lambda's initial creation. Permits the same usage as // XStr("literal").unicodeForm() +// XStrLiteral macro use local memory manager instance to prevent segfault on releasing cached +// string because xerces default memory manager is already deleted when destructing local static +// variable. #define XStrLiteral(literal) \ ([]() -> const XStr& { \ - static const XStr str {literal}; \ + static XStrMemoryManager memMgr; \ + static const XStr str {literal, &memMgr}; \ return str; \ }())