Something in the following code is leaking memory, but I can't find it.
I've traced through it with a debugger, and even with a debug build, it won't step into the ref counting. So I've planted pairs of .AddRef() and .Release() to see the ref count of all the pointers at various points. The thing that stands out to me is the result of createProcessingInstruction has a ref count of 2. If I try to manually decrement it with .Release(), the app triggers an assertion later in the code.
The outer brace in the code below is part of my code, so all of the smart pointers in there should release at the end. parser outlives this section, and was determined to not be part of the leak.
When I run this code in a loop the Commit Size (and naturally Peak Commit Size) grows steadily in all Task Manager, Process Explorer, and programmatically via GetProcessMemoryInfo.
MSXML2::IXMLDOMDocument3Ptr parser;
HRESULT hr(parser.CreateInstance(__uuidof(MSXML2::DOMDocument60) ) );
if(FAILED(hr) )
{
throw(XmlException("Failed to create instance of MSXML."));
}
parser->preserveWhiteSpace = VARIANT_TRUE;
...
// Various methods to populate the XML. Omitted because this was determined to not leak
...
// Something within this section is leaking.
{
const std::wstring wstrXmlDeclaration(L" version=\"1.0\" encoding=\"UTF-16\"");
// TODO: If this is expensive, maybe store an instance?
IXMLDOMProcessingInstructionPtr pProcessingInstruction(
parser->createProcessingInstruction(
L"xml",
wstrXmlDeclaration.c_str()
)
);
if(!pProcessingInstruction)
{
throw(XmlException("Failed to create instruction for encoding.") );
}
DWORD ulRefCount = pProcessingInstruction->AddRef();
ulRefCount = pProcessingInstruction->Release();
// NOTE: ulRefCount is 2 here (??)
MSXML2::IXMLDOMNodePtr pFirstChild(
parser->GetfirstChild()
);
if(!pFirstChild)
{
throw(XmlException("Failed to get XML Declaration of XML Document.") );
}
const std::wstring wstrFirstChildName(pFirstChild->nodeName);
assert(wstrFirstChildName == L"xml");
if(wstrFirstChildName != L"xml")
{
throw(XmlException("Unexpected first element (XML Declaration) in XML."));
}
MSXML2::IXMLDOMNodePtr pOldChild(
parser->replaceChild(
static_cast<MSXML2::IXMLDOMNode*>(pProcessingNode),
static_cast<MSXML2::IXMLDOMNode*>(pFirstChild)
)
);
if(!pOldChild)
{
throw(XmlException("Failed to apply specified encoding.") );
}
}