Details
-
Improvement
-
Status: Closed
-
Critical
-
Resolution: Invalid
-
1.5, 1.5.1, 1.5.2, 1.6.0
-
None
-
None
-
WinXP/VC7.1
Description
a)Problem description:
Once TransService is used to create a new XMLTranscoder, no other feasible way to clear up the memory except for calling XMLTranscoder destructor explicitly. The signature of the creation function is as follows:
XMLTranscoder* XMLTransService::makeNewTranscoderFor
b)Analyzed the problem:
i.The class tree is XMemory --> XMLTranscoder --> XMLUTF8Transcoder. The delete/new operators in the base class were overloaded with pluggable memory manager (default is Xerces’ MemoryManager class implementation, which currently uses global operators ::operator delete, ::operator new in a straightforward manner). The function signature is like this:
void* XMemory::operator new(size_t size, MemoryManager* manager)
void XMemory::operator delete(void* p, MemoryManager* manager)
ii.Although the definitions for the above new/delete appeared symmetric, they are actually not. In C++, there is a way of calling this overloaded new operator using “replacement new” syntax: e.g., new (manager) XMLTranscoder( ), which will call the overloaded new operator (do some memory allocation in this case) first and then call the class constructor (do some further memory allocation in this case). Unfortunately, there is no such a “replacement delete” that will “undo” these things automatically. As a result, whenever “placement new” was used, for releasing the memory, the destructor should be called explicitly first, then the overloaded delete should be called (so that the corresponding memory manager is used) to free up the memory. See BJARNE’s C++ Programming Language (3rd Edition) Page 256 for detailed explanation.
iii.Debugging into method makeNewTranscoderFor( ) reveals that it called “replacement new” to do the memory allocation:
template <class TType> XMLTranscoder*
ENameMapFor<TType>::makeNew(const unsigned int blockSize,
MemoryManager* const manager) const
{
return new (manager) TType(getKey(), blockSize, manager);
}
but it seemed to me that Xerces did not provide a corresponding method to release&clean up objects (at lease in current releases 2.5.0 and 2.6.0)
iv.Without a corresponding destroyTranscoder(...) to hide the detail of releasing the memory for me, I have to use the following “messy” code:
//create a new transcoder
XMLTranscoder* aTranscoder = XMLPlatformUtils::fgTransService->
makeNewTranscoderFor(encodingName, resCode, 16*maxBufferSize,
XMLPlatformUtils::fgMemoryManager);
//do some work with the transcoder
...
//messy code for releasing all the memory
aTranscoder->~XMLTranscoder(); //release the memory allocated in constructor
aTranscoder->operator delete(aTranscoder, XMLPlatformUtils::fgMemoryManager); //release the memory allocated by replacment new
c) Proposed improvement
XMLTransService should provide a corresponding DestroyTranscoder(...) method that will internally call the above two lines of code so that the implementation detail is hidden to the Xerces users.