aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Kummerländer2014-04-23 21:26:58 +0200
committerAdrian Kummerländer2014-04-23 21:26:58 +0200
commit525aa8c4dc3e23f0369c7edb1fb507ecad5f43bf (patch)
tree6044c2876a55ed4c794bd577909225c49015d402
parent30ae1cc66daf8acbb556ec761f96690a2fa74637 (diff)
downloadInputXSLT-525aa8c4dc3e23f0369c7edb1fb507ecad5f43bf.tar
InputXSLT-525aa8c4dc3e23f0369c7edb1fb507ecad5f43bf.tar.gz
InputXSLT-525aa8c4dc3e23f0369c7edb1fb507ecad5f43bf.tar.bz2
InputXSLT-525aa8c4dc3e23f0369c7edb1fb507ecad5f43bf.tar.lz
InputXSLT-525aa8c4dc3e23f0369c7edb1fb507ecad5f43bf.tar.xz
InputXSLT-525aa8c4dc3e23f0369c7edb1fb507ecad5f43bf.tar.zst
InputXSLT-525aa8c4dc3e23f0369c7edb1fb507ecad5f43bf.zip
Fixed xerces DOM construction related memory leaks
* Wrapped xerces DOM and support class instances in now DomDocumentGuard scope-guard class * FunctionReadDirectory class contains interal std::stack instance to store DomDocumentGuard instances ** wrapped in std::shared_ptr as FunctionReadDirectory is internally cloned by xalan... ** this is needed as the DOM has to preserved longer than the external function execution scope * Sadly XMLCh xerces strings have to be manually released ** added appropriate xercesc::XMLString::release calls * xalan::XercesDOMWrapperParsedSource does not mirror a given xerces DOM but convert it on instantiation ** this is why there is a dedicated finalize member method in InputXSLT::DomDocumentGuard * In short: I do not like the amount of trickery needed to simply prevent memory leaks in this context ** there sadly doesn't seem to be a substantially easier way to return arbitrary DOM trees from a external function
-rw-r--r--CMakeLists.txt1
-rw-r--r--src/function/read_directory.cc48
-rw-r--r--src/function/read_directory.h10
-rw-r--r--src/support/dom_document_guard.cc45
-rw-r--r--src/support/dom_document_guard.h36
-rw-r--r--src/transformer_facade.cc2
6 files changed, 101 insertions, 41 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 915a05d..94ade96 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,6 +18,7 @@ add_executable(
src/function/read_xml_file.cc
src/function/read_directory.cc
src/support/filesystem_context.cc
+ src/support/dom_document_guard.cc
)
target_link_libraries(
diff --git a/src/function/read_directory.cc b/src/function/read_directory.cc
index a4284c0..6d643da 100644
--- a/src/function/read_directory.cc
+++ b/src/function/read_directory.cc
@@ -1,25 +1,16 @@
#include "read_directory.h"
-#include <xalanc/XercesParserLiaison/XercesDOMSupport.hpp>
-#include <xalanc/XalanTransformer/XercesDOMWrapperParsedSource.hpp>
-
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMText.hpp>
#include <xercesc/util/XMLString.hpp>
-#include <sstream>
-
namespace InputXSLT {
FunctionReadDirectory::FunctionReadDirectory(const FilesystemContext& context):
fs_context_(context),
- parser_() { }
-
-FunctionReadDirectory::FunctionReadDirectory(const FunctionReadDirectory& src):
- fs_context_(src.fs_context_),
- parser_() { }
+ documents_(new std::stack<DomDocumentGuard>()) { }
xalan::XObjectPtr FunctionReadDirectory::execute(
xalan::XPathExecutionContext& executionContext,
@@ -35,44 +26,29 @@ xalan::XObjectPtr FunctionReadDirectory::execute(
this->generalError(executionContext, context, locator);
}
- xercesc::DOMDocument* const inputDom(
- xercesc::DOMImplementation::getImplementation()->createDocument(
- nullptr, xercesc::XMLString::transcode("content"), nullptr
- )
- );
+ this->documents_->emplace("content");
+ DomDocumentGuard& domDocument = this->documents_->top();
- xercesc::DOMNode* const rootNode = inputDom->getDocumentElement();
+ xercesc::DOMNode* const rootNode = domDocument->getDocumentElement();
this->fs_context_.iterate(
arguments[0]->str(),
- [&inputDom, &rootNode](const boost::filesystem::path& p) {
- xercesc::DOMNode* const fileNode = inputDom->createElement(
- xercesc::XMLString::transcode("file")
- );
+ [&domDocument, &rootNode](const boost::filesystem::path& p) {
+ XMLCh* buffer = xercesc::XMLString::transcode("file");
+ xercesc::DOMNode* const fileNode = domDocument->createElement(buffer);
+ xercesc::XMLString::release(&buffer);
- xercesc::DOMText* const textNode = inputDom->createTextNode(
- xercesc::XMLString::transcode(p.filename().string().data())
- );
+ buffer = xercesc::XMLString::transcode(p.filename().string().data());
+ xercesc::DOMText* const textNode = domDocument->createTextNode(buffer);
+ xercesc::XMLString::release(&buffer);
fileNode->appendChild(textNode);
rootNode->appendChild(fileNode);
});
-
- xalan::XercesDOMSupport domSupport(this->parser_);
-
- xalan::XercesDOMWrapperParsedSource* const parsedSource(
- new xalan::XercesDOMWrapperParsedSource(
- inputDom,
- this->parser_,
- domSupport
- )
- );
-
return executionContext.getXObjectFactory().createNodeSet(
- parsedSource->getDocument()
+ domDocument.finalize()
);
-
}
FunctionReadDirectory* FunctionReadDirectory::clone(
diff --git a/src/function/read_directory.h b/src/function/read_directory.h
index e7ee0c4..3c55591 100644
--- a/src/function/read_directory.h
+++ b/src/function/read_directory.h
@@ -6,19 +6,18 @@
#include <xalanc/XPath/Function.hpp>
#include <xalanc/XPath/XObject.hpp>
-#include <xalanc/XercesParserLiaison/XercesParserLiaison.hpp>
-
-#include <string>
+#include <memory>
+#include <stack>
#include "common.h"
#include "support/filesystem_context.h"
+#include "support/dom_document_guard.h"
namespace InputXSLT {
class FunctionReadDirectory : public xalan::Function {
public:
FunctionReadDirectory(const FilesystemContext&);
- FunctionReadDirectory(const FunctionReadDirectory&);
virtual xalan::XObjectPtr execute(
xalan::XPathExecutionContext&,
@@ -34,7 +33,8 @@ class FunctionReadDirectory : public xalan::Function {
private:
const FilesystemContext& fs_context_;
- mutable xalan::XercesParserLiaison parser_;
+
+ std::shared_ptr<std::stack<DomDocumentGuard>> documents_;
const xalan::XalanDOMString& getError(xalan::XalanDOMString&) const;
diff --git a/src/support/dom_document_guard.cc b/src/support/dom_document_guard.cc
new file mode 100644
index 0000000..a83345f
--- /dev/null
+++ b/src/support/dom_document_guard.cc
@@ -0,0 +1,45 @@
+#include "support/dom_document_guard.h"
+
+#include <xercesc/dom/DOMImplementation.hpp>
+#include <xercesc/util/XMLString.hpp>
+
+namespace InputXSLT {
+
+DomDocumentGuard::DomDocumentGuard(const std::string& rootNode):
+ parser_(),
+ dom_support_(parser_),
+ root_node_name_(
+ xercesc::XMLString::transcode(rootNode.data())
+ ),
+ document_(
+ xercesc::DOMImplementation::getImplementation()->createDocument(
+ nullptr,
+ root_node_name_,
+ nullptr
+ )
+ ),
+ parsed_source_() { }
+
+DomDocumentGuard::~DomDocumentGuard() {
+ xercesc::XMLString::release(&this->root_node_name_);
+
+ this->document_->release();
+}
+
+xercesc::DOMDocument* DomDocumentGuard::operator->() {
+ return this->document_;
+}
+
+xalan::XalanDocument* DomDocumentGuard::finalize() {
+ this->parsed_source_.reset(
+ new xalan::XercesDOMWrapperParsedSource(
+ document_,
+ parser_,
+ dom_support_
+ )
+ );
+
+ return this->parsed_source_->getDocument();
+}
+
+}
diff --git a/src/support/dom_document_guard.h b/src/support/dom_document_guard.h
new file mode 100644
index 0000000..decca01
--- /dev/null
+++ b/src/support/dom_document_guard.h
@@ -0,0 +1,36 @@
+#ifndef INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_GUARD_H_
+#define INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_GUARD_H_
+
+#include <xalanc/XercesParserLiaison/XercesParserLiaison.hpp>
+#include <xalanc/XercesParserLiaison/XercesDOMSupport.hpp>
+#include <xalanc/XalanTransformer/XercesDOMWrapperParsedSource.hpp>
+
+#include <xercesc/dom/DOMDocument.hpp>
+
+#include <string>
+#include <memory>
+
+#include "common.h"
+
+namespace InputXSLT {
+
+class DomDocumentGuard {
+ public:
+ DomDocumentGuard(const std::string&);
+ ~DomDocumentGuard();
+
+ xercesc::DOMDocument* operator->();
+ xalan::XalanDocument* finalize();
+
+ private:
+ xalan::XercesParserLiaison parser_;
+ xalan::XercesDOMSupport dom_support_;
+ XMLCh* root_node_name_;
+ xercesc::DOMDocument* const document_;
+ std::unique_ptr<xalan::XercesDOMWrapperParsedSource> parsed_source_;
+
+};
+
+}
+
+#endif // INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_GUARD_H_
diff --git a/src/transformer_facade.cc b/src/transformer_facade.cc
index 01314cd..fbf604c 100644
--- a/src/transformer_facade.cc
+++ b/src/transformer_facade.cc
@@ -59,6 +59,8 @@ int TransformerFacade::execute(
domSupport
);
+ inputDom->release();
+
xalan::XSLTInputSource transform(transformation.data());
xalan::XSLTResultTarget output(target.data());