Project

Profile

Help

RE: Returned object deletion ยป SaxonDeleteTest.cpp

Paul Greve, 2025-01-04 19:27

 
#include <iostream>
#include <sys/sysinfo.h>
#include "SaxonProcessor.h"
#include "XdmNode.h"

using namespace std;

XdmNode *getElement(XdmNode *, const std::string, SaxonProcessor*);
XdmNode *getRoot(XdmNode *);
void printElement(XdmNode *);
void printChildren(XdmNode *);

int main(int argc, char* argv[])
{
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!

std::string xml =
"<root root-attribute=\"root-attribute-data\">\n"
" <first-child first-child-attribute=\"first-child-attribute-data\">\n"
" first-child-data\n"
" </first-child>\n"
" <second-child second-child-attribute=\"second-child-attribute-data\">\n"
" second-child-data\n"
" </second-child>\n"
" <third-child third-child-attribute=\"third-child-attribute-data\">\n"
" third-child-data\n"
" </third-child>\n"
"</root>\n";


printf("XML: %s\n", xml.c_str());

SaxonProcessor * processor = new SaxonProcessor(true);
processor->setConfigurationProperty("http://saxon.sf.net/feature/licenseFileLocation",
"/usr/lib/saxon-j/saxon-license.lic");
processor->setConfigurationProperty("http://saxon.sf.net/feature/multipleSchemaImports", "on");
processor->setConfigurationProperty("xsdversion", "1.0");

try
{
// parser the XML
XdmNode *document = processor->parseXmlFromString(xml.c_str());

if (document == nullptr)
{
fprintf(stderr, "Parsing of XML failed\n");
return -1;
}

// get the root element
std::string rootElementName = "root";

//
/**
* ISSUE #2:
* Regardless of whether you use getElement or getRoot() to get the
* root element, deleting the node at the end of the program gives a
* 'double free detected in tcache 2' error
*/
#if 1
XdmNode *root = getElement(document, rootElementName.c_str(), processor);
#else
XdmNode *root = getRoot(document);
#endif

if (root == nullptr)
{
fprintf(stderr, "Could not get root element\n");
return -1;
}

/**
* ISSUE #4:
* If you make a copy of the XdmNode in getRoot(),
* this returns NULL
*/
// get the root element's value
const char *rootElementValue = root->getStringValue();

if (rootElementValue != nullptr)
{
printf("Root element: Name=%s, Value=%s\n", rootElementName.c_str(),
rootElementValue);

operator delete((char *)rootElementValue);
}

// // print the root element
// printElement(root);

// get the root's attribute value
std::string rootAttributeName = "root-attribute";

/**
* ISSUE #4:
* If you make a copy of the XdmNode in getRoot(),
* this returns throws a ava.lang.NullPointerException
* at net.sf.saxon.option.cpp.XdmUtils.getAttributeValue(XdmUtils.java:1262)
*/
const char *rootAttributeValue = root->getAttributeValue(rootAttributeName.c_str());

if (rootAttributeValue != nullptr)
{
printf("Root attribute: Name=%s, Value=%s\n", rootAttributeName.c_str(),
rootAttributeValue);

#if 0
/**
* ISSUE #1:
* This gives 'double free or corruption' error
*/
operator delete((char *)rootAttributeValue);
#endif
}

printChildren(root);
#if 0
/**
* ISSUE #3:
* A second call to printChildren gives a SEG FAULT (SIGSEGV)
*/
printChildren(root);
#endif

#if 1
/**
* ISSUE #2:
* This gives double free detected in tcache 2 regardless of
* whether you use getRoot() or getElement() to get the root node
*/
delete root;
#endif
delete document;
}
catch(SaxonApiException &e)
{
cout<<"Exception parsing XML: "<<e.what()<<endl;
}

delete processor;
SaxonProcessor::release();

return 0;
}

XdmNode *getRoot(XdmNode *document)
{
XdmNode *root = nullptr;

XdmNode **children = document->getChildren();

if (children != nullptr)
{
int childCount = document->getChildCount();
bool found = false;
for (int i=0; i<childCount; i++)
{
XdmNode *child = children[i];
if (child != nullptr)
{
if (found)
{
delete child;
}
else if (child->getNodeKind() == XDM_NODE_KIND::ELEMENT)
{
#if 0
/**
* ISSUE #4:
* If you make a copy of the node, calls to it return nullptrs
* or throw java NullPointerExceptions.
*/
// Make a copy so we can pass it around
root = new XdmNode(*child);
delete child;
#else
root = child;
#endif
found = true;
}
}
}
delete [] children;
}


return root;
}

XdmNode *getElement(XdmNode *node, const std::string name, SaxonProcessor* processor)
{
XdmNode *element = nullptr;

XPathProcessor *xpath = processor->newXPathProcessor();
xpath->setLanguageVersion("3.1");

std::string xpathExpression = "//" + name;

try
{
xpath->setContextItem((XdmItem *)node);

XdmValue *elements = xpath->evaluate(xpathExpression.c_str());
printf("XPath expression: %s, # of values returned: %d\n",
xpathExpression.c_str(), elements->size());

if (elements->size())
{
XdmItem * item = elements->itemAt(0);

if ((item != nullptr) && (item->getType() == XDM_TYPE::XDM_NODE))
{
/**
* ISSUE #2:
* Regardless of whether or you make a copy of the XdmItem
* you get a 'double free detected in tcache 2' error when
* you delete it.
*/
#if 1
// Make a copy so we can pass it around
element = new XdmNode(*((XdmNode *)item));
#else
element = (XdmNode *)item;
#endif
}
}

delete elements;
}
catch(SaxonApiException &e)
{
printf("Exception evaluating xpath expression %s: %s\n",
xpathExpression.c_str(), e.what());
}

delete xpath;

return element;
}

void printElement(XdmNode * node)
{
printf("Element:\n");
printf(" Name: %s\n", node->getLocalName());
printf(" # of Children: %d\n", node->getChildCount());

int attributeCount = node->getAttributeCount();
printf(" # of Attributes: %d\n", attributeCount);
printf("\n");
}


void printChildren(XdmNode *node)
{
XdmNode **children = node->getChildren();
if (children != nullptr)
{
int childCount = node->getChildCount();
for (int i=0; i<childCount; i++)
{
XdmNode *child = children[i];
if (child != nullptr)
{
if (child->getNodeKind() == XDM_NODE_KIND::ELEMENT)
{
printElement(child);
}

/**
* ISSUE #3:
* If you make a second call to printChildren(),
* this gives SEG FAULT (SIGSEGV)
*/
delete child;
}
}

delete [] children;
}
}
    (1-1/1)