Проблемы с Xerces-C;ошибка при вызове деструктора объекта
-
12-09-2019 - |
Вопрос
Я тут поиграл с Ксеркес-С Библиотека XML.
У меня есть этот простой пример, с которым я играю.
Кажется, я не могу запустить его без утечки памяти и без сегментации.Это либо одно, либо другое.
Ошибка segfault всегда возникает, когда я удаляю объект синтаксического анализатора в разделе "Очистка".
Я пробовал использовать обе версии библиотеки 2.8 и 2.7.
Примечание: Я удалил всю проверку исключений из кода, я получаю одинаковые результаты с ним и без него.Для удобства чтения и простоты я удалил его из приведенного ниже кода.
Кто-нибудь из подкованных в Ксерксе людей может внести какие-нибудь предложения?
Я не могу особо отличить обратную трассировку, она просто переходит в деструктор суперкласса и выполняет сегментацию там.
Обратный путь:
(gdb) bt
#0 0x9618ae42 in __kill ()
#1 0x9618ae34 in kill$UNIX2003 ()
#2 0x961fd23a in raise ()
#3 0x96209679 in abort ()
#4 0x95c5c005 in __gnu_cxx::__verbose_terminate_handler ()
#5 0x95c5a10c in __gxx_personality_v0 ()
#6 0x95c5a14b in std::terminate ()
#7 0x95c5a6da in __cxa_pure_virtual ()
#8 0x003e923e in xercesc_2_8::AbstractDOMParser::cleanUp ()
#9 0x003ead2a in xercesc_2_8::AbstractDOMParser::~AbstractDOMParser ()
#10 0x0057022d in xercesc_2_8::XercesDOMParser::~XercesDOMParser ()
#11 0x000026c9 in main (argc=2, argv=0xbffff460) at test.C:77
Код:
#include <string>
#include <vector>
#if defined(XERCES_NEW_IOSTREAMS)
#include <iostream>
#else
#include <iostream.h>
#endif
#include <xercesc/dom/DOM.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
using namespace std;
XERCES_CPP_NAMESPACE_USE
int main(int argc, char const* argv[])
{
string skXmlMetadata = "<?xml version=\"1.0\"?>\n <xmlMetadata>b</xmlMetadata>";
XMLPlatformUtils::Initialize();
XercesDOMParser* xmlParser = NULL;
DOMWriter* xmlWriter = NULL;
ErrorHandler* errHandler = NULL;
const XMLByte* xmlBuf = NULL;
MemBufInputSource* memBufIS = NULL;
DOMNode* xmlDoc = NULL;
xmlParser = new XercesDOMParser();
xmlParser->setValidationScheme( XercesDOMParser::Val_Never );
xmlParser->setDoNamespaces( false );
xmlParser->setDoSchema( false );
xmlParser->setLoadExternalDTD( false );
errHandler = (ErrorHandler*) new HandlerBase();
xmlParser->setErrorHandler( errHandler );
// Create buffer for current xmlMetadata
xmlBuf = (const XMLByte*) skXmlMetadata.c_str();
const char* bufID = "XmlMetadata";
memBufIS = new MemBufInputSource( xmlBuf, skXmlMetadata.length(), bufID, false );
// Parse
xmlParser->resetErrors();
xmlParser->parse( *memBufIS );
xmlDoc = xmlParser->getDocument();
// Write created xml to input SkArray
XMLCh* metadata = NULL;
xmlWriter = DOMImplementation::getImplementation()->createDOMWriter();
xmlWriter->setFeature( XMLUni::fgDOMWRTFormatPrettyPrint, true );
metadata = xmlWriter->writeToString( *xmlDoc );
xmlWriter->release();
// Print out our parsed document
char* xmlMetadata = XMLString::transcode( metadata );
string c = xmlMetadata;
cout << c << endl;
// Clean up
XMLString::release( &xmlMetadata );
xmlDoc->release();
delete xmlParser; // Dies here
delete memBufIS;
delete errHandler;
XMLPlatformUtils::Terminate();
return 0;
}
Решение
" xmlDoc->release();- это и есть виновник.Вы не являетесь владельцем этого узла, пока не скажете " XMLParser-> adoptDocument() ".
Другие советы
Давайте рассмотрим доказательства...
#6 0x95c5a14b in std::terminate ()
Я могу сказать вам, что это вызывается, когда деструктор генерирует исключение.Деструкторы, выбрасывающие исключения, - это большой запрет.Ксеркс, возможно, делает что-то нехорошее.
Или это может быть вызвано этой строкой
#7 0x95c5a6da in __cxa_pure_virtual ()
где что-то может отсутствовать в таблице виртуальных функций.Возможно, деструктор одного из элементов DOM-объекта?Возможно, это порождает исключение?
Эта ссылка предлагает отличное объяснение того, что может привести к сбою поиска в виртуальной таблице.Короче говоря, это может быть вызвано зависшим указателем базового класса, висящим вокруг кого-то, пытающегося вызвать полиморфную функцию по этому указателю.
Пример приведен по ссылке выше:
// From sample program 5:
AbstractShape* p1 = new Rectangle(width, height, valuePerSquareUnit);
std::cout << "value = " << p1->value() << std::endl;
AbstractShape* p2 = p1; // Need another copy of the pointer.
delete p1;
std::cout << "now value = " << p2->value() << std::endl;
Говоря о висячих указателях, похоже, что XercesDomParser содержит объекты, которые вы обновили:
errHandler = (ErrorHandler*) new HandlerBase();
xmlParser->setErrorHandler( errHandler )
но позже удален / выпущен
// Clean up
XMLString::release( &xmlMetadata );
xmlDoc->release();
delete xmlParser;
delete memBufIS;
delete errHandler;
Может ли порядок, в котором вы уничтожаете вещи, быть неправильным и вызывать некоторые из вышеперечисленных проблем?На первый взгляд, все выглядит нормально, но именно здесь я бы поэкспериментировал и дважды проверил документацию о том, как все должно быть снесено.
Я не вижу ничего явно неправильного в коде.Возможно, вы захотите попробовать удалить все варианты использования new и delete в коде и вместо этого создать объекты Cerces, которые вы используете как объекты на основе стека.Например, вместо:
xmlParser = new XercesDOMParser();
использование:
XercesDOMParser xmlParser;
и так далее.