Today I was trying to find memory leaks from my project then I came across the below sample code
std::string VersionValue("1.0");
std::string EncodingValue("UTF-8");
rapidxml::xml_document<> XMLDoc;
rapidxml::xml_node<> * pHeaderNode = XMLDoc.allocate_node(rapidxml::node_declaration);
pHeaderNode->append_attribute(XMLDoc.allocate_attribute("version", VersionValue.c_str()));
pHeaderNode->append_attribute(XMLDoc.allocate_attribute("encoding", EncodingValue.c_str()));
I opened rapidxml code, inside allocate_attribute() I saw its allocating memory
xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>;
and inside append_attribute()
its assigning the memory to its member variable.
There is no destructor function declared for xml_document
. Then how its deleting the attributes? valgrind is returned 0 memory leaks from the above sample code. How its possible?
As mentioned in comments, placement new is the answer.
This behaviour is one of the major benefits - and one of the most common gotchas - with rapidxml: It doesn't make copies of any of the data passed as parameters.
For example, if your code looked like this:-
rapidxml::xml_document<> XMLDoc;
rapidxml::xml_node<> * pHeaderNode =
XMLDoc.allocate_node(rapidxml::node_declaration);
{
std::string VersionValue("1.0");
std::string EncodingValue("UTF-8");
pHeaderNode->append_attribute(XMLDoc.allocate_attribute("version", VersionValue.c_str()));
pHeaderNode->append_attribute(XMLDoc.allocate_attribute("encoding", EncodingValue.c_str()))
}
... then you'll usually have major problems because the attribute strings will go out of scope but rapidxml will continue to hold stale pointers to them.