2009-06-06 6 views
3

J'ai joué avec la bibliothèque XML Xerces-C.Problèmes Xerces-C; segfault sur appel à un destructeur d'objet

J'ai cet exemple simple avec lequel je joue.

Je n'arrive pas à l'exécuter sans fuites de mémoire et sans segfault. C'est l'un ou l'autre.

La segfault se produit toujours lorsque je supprime l'objet analyseur sous "Nettoyage".

J'ai essayé d'utiliser à la fois les versions 2.8 & 2.7 de la bibliothèque.

Remarque: J'ai pris toutes les vérifications d'exception du code, j'obtiens le même résultat avec et sans. Pour plus de lisibilité et de simplicité, je l'ai retiré du code ci-dessous.

Est-ce que les gens avertis de Xerces sont là pour vous faire des suggestions?

Je ne peux pas vraiment dire grand-chose de la trace arrière, c'est juste de sauter dans le destructeur de la super-classe et segfaulting là.

Backtrace:

(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 

Le 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; 
} 
+1

Il peut aider les gens à zéro sur votre problème si vous pouvez pointer sur la ligne 77 qui est dans votre source. Peut-être un commentaire de fin de ligne comme "// meurt ici"? –

+0

Donc, je ne connais pas Xerces, mais avez-vous essayé d'utiliser RAII avec un fichier std :: auto_ptr ou similaire? Si vous voulez éviter cela, je supprime généralement les éléments dans l'ordre inverse, je les nouveaux. Il peut y avoir une interaction étrange entre le xmlParser et le gestionnaire d'erreurs, car vous supprimez le xmlParser avant errorHandler? – jdt141

+0

Les analyseurs Xerces ne possèdent pas leurs gestionnaires d'erreurs, c'est donc l'ordre correct. –

Répondre

1

permet d'explorer les éléments de preuve ...

#6 0x95c5a14b in std::terminate() 

Je peux vous dire ceci est appelé lorsqu'un destructeur jette un exce ption. Destructeurs jetant des exceptions est un gros non-non. Xerces peut faire quelque chose de bancal.

Ou il pourrait être causé par cette ligne

#7 0x95c5a6da in __cxa_pure_virtual() 

où quelque chose peut-être manquant dans une table de fonction virtuelle. Peut-être l'un des membres de l'objet DOM destructeur? Peut-être cela génère une exception?

This linkThis link offre une excellente explication de ce qui pourrait provoquer l'échec des recherches de table virtuelle. En bref, il peut être provoqué par un pointeur de classe de base qui pend autour de quelqu'un essayant de faire un appel de fonction polymorphe sur ce pointeur.

Exemple donné à partir du lien ci-dessus:

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

En parlant de pointeurs ballants, il semble que le XercesDomParser tient objets newed:

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

mais plus tard supprimé/publié

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

L'ordre que vous détruisez les choses peut-il être incorrect et provoquer des problèmes ci-dessus?À première vue, les choses semblent bien, mais c'est là que j'expérimenterais et vérifierais la documentation sur la façon dont les choses sont censées être démolies.

+1

Les analyseurs Xerces ne possèdent pas leurs gestionnaires d'erreurs et ne les suppriment pas. –

+0

J'ai essayé un bloc try/catch autour de la suppression de xmlParser avant de poser la question, car @Doug T n'a mentionné aucune exception. –

0

Je ne vois rien de manifestement faux avec le code. Vous pouvez essayer de supprimer toutes les utilisations du nouveau & dans le code et créer les objets Cerces que vous utilisez comme base de pile objectys à la place. Par exemple, au lieu de:

xmlParser = new XercesDOMParser(); 

utilisation:

XercesDOMParser xmlParser; 

et ainsi de suite.

+0

Essayé que, encore segfaults dans le déconstructeur de la pile basée XercesDOMParser :( –

Questions connexes