3 Stimmen

Xerces-C-Probleme; Segfault beim Aufruf des Objekt-Destruktors

Ich habe mich mit der Xerces-C XML-Bibliothek.

Ich habe dieses einfache Beispiel, mit dem ich spiele.

Ich kann es nicht zum Laufen bringen, ohne dass Speicher verloren geht und ohne dass es zu Segfehlern kommt. Es ist entweder das eine oder das andere.

Der Segfault tritt immer auf, wenn ich das Parser-Objekt unter "Aufräumen" lösche.

Ich habe versucht, sowohl die 2.8- als auch die 2.7-Version der Bibliothek zu verwenden.

Anmerkung: Ich habe die gesamte Ausnahmeprüfung aus dem Code entfernt und erhalte mit und ohne sie die gleichen Ergebnisse. Für Lesbarkeit und Einfachheit habe ich es aus dem Code unten entfernt.

Kann jemand, der sich mit Xerces auskennt, einige Vorschläge machen?

Ich kann nicht wirklich viel von der Rückverfolgung sagen, es ist nur Springen nach unten in die Superklasse Destruktor und Segfaulting dort.

Zurückverfolgen:

(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

Der Code:

#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;
}

9voto

Shiva Punkte 116

" xmlDoc->release(); " ist der Übeltäter. Sie besitzen diesen Knoten nicht, es sei denn, Sie sagen "xmlParser->adoptDocument()".

http://xerces.apache.org/xerces-c/apiDocs-2/classAbstractDOMParser.html#fe052561c37d70b62ac57ab6706d75aa

1voto

Doug T. Punkte 61739

Lassen Sie uns die Beweise untersuchen...

#6  0x95c5a14b in std::terminate ()

Ich kann Ihnen sagen, dass dies aufgerufen wird, wenn ein Destruktor eine Ausnahme auslöst. Destruktoren, die Ausnahmen auslösen, sind ein großes Tabu. Xerces macht vielleicht etwas falsch.

Oder es könnte durch diese Zeile verursacht werden

#7  0x95c5a6da in __cxa_pure_virtual ()

wo in einer virtuellen Funktionstabelle etwas fehlen könnte. Vielleicht eines der Mitglieder des DOM-Objekts destructor? Vielleicht erzeugt dies eine Ausnahme?

Dieser Link bietet eine gute Erklärung dafür, was die Ursache für das Scheitern der virtuellen Tabellensuche sein könnte. Kurz gesagt, kann es durch einen baumelnden Basisklassenzeiger verursacht werden, der herumhängt, wenn jemand versucht, einen polymorphen Funktionsaufruf auf diesen Zeiger zu machen.

Beispiel aus dem obigen Link:

// 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;

Apropos baumelnde Zeiger, es sieht so aus, als ob der XercesDomParser Objekte enthält, die Sie neu eingegeben haben:

  errHandler = (ErrorHandler*) new HandlerBase();
  xmlParser->setErrorHandler( errHandler )

aber später gelöscht/freigegeben

  // Clean up
  XMLString::release( &xmlMetadata );
  xmlDoc->release();
  delete xmlParser;
  delete memBufIS;
  delete errHandler;

Könnte die Reihenfolge, in der Sie die Dinge zerstören, falsch sein und einige der oben genannten Probleme verursachen? Auf den ersten Blick scheint alles in Ordnung zu sein, aber an dieser Stelle würde ich experimentieren und in der Dokumentation nachlesen, wie die Dinge abgerissen werden sollen.

0voto

Ich kann keinen offensichtlichen Fehler in dem Code erkennen. Sie könnten versuchen, alle Verwendungen von new & delete im Code zu entfernen und stattdessen die von Ihnen verwendeten Cerces-Objekte als stapelbasierte Objekte zu erstellen. Zum Beispiel, anstelle von:

xmlParser = new XercesDOMParser();

verwenden:

XercesDOMParser xmlParser;

und so weiter.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X