We're using libxml2 to resolve xpaths against an xmlcontext which contains "registered" vars. Our destructor attempts to clean up an xmlXPathContextPtr and a xmlDocPtr:
~CLibXpathContext()
{
xmlXPathFreeContext(m_xpathContext); //causes crash if any vars registered
xmlFreeDoc(m_xmlDoc);
}
We're registering vars as follows:
virtual bool addVariable(const char * name, const char * val) override
{
if (m_xpathContext )
{
xmlXPathObjectPtr valx = xmlXPathWrapCString((char*)val);
return xmlXPathRegisterVariable(m_xpathContext, (xmlChar *)name, valx) == 0;
}
return false;
}
The libxml2 cleanup code is as follows:
void xmlXPathFreeContext(xmlXPathContextPtr ctxt) {
if (ctxt == NULL) return;
if (ctxt->cache != NULL)
xmlXPathFreeCache((xmlXPathContextCachePtr) ctxt->cache);
xmlXPathRegisteredNsCleanup(ctxt);
xmlXPathRegisteredFuncsCleanup(ctxt);
xmlXPathRegisteredVariablesCleanup(ctxt); // this is causing the issue
xmlResetError(&ctxt->lastError);
xmlFree(ctxt);
}
Any ideas what I might be doing wrong, or if the libxml2 code has an issue?
We also attempted to unregister all registered vars before calling the xmlXPathFreeContext method...
You have to use xmlXPathNewCString(const char *)
instead of xmlXPathWrapCString(char *)
. The former creates a copy of the string while the latter transfers ownership of the string to the XPath object, freeing the original string when the XPath object is destroyed.