2009-06-06 7 views
3

私はXerces-C XMLライブラリで遊んでいます。Xerces-Cの問題。オブジェクトデストラクタの呼び出し時にsegfault

私はこの単純な例を持っています。

メモリが漏れず、セグメンテーションがないと実行できないようです。 それはどちらか一方です。

segfaultは、「クリーンアップ」でパーサオブジェクトを削除すると常に発生します。

2.8 & 2.7バージョンのライブラリを使用してみました。

注:私はすべての例外チェックをコードから取り除きましたが、私はそれを使って同じ結果を得ました。読みやすくてシンプルにするために、私は以下のコードから削除しました。

Xercesに精通している人々は、いくつかの提案をするのに気をつけていますか?

私はバックトレースから実際には分かりませんが、スーパークラスのデストラクタにジャンプし、そこにセグメンテーションしています。

バックトレース:

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

それはあなたがあなたのソース内の行77である指摘することができた場合に人々はあなたの問題をゼロに役立つことがあります。 「//ここで死ぬ」のような行末コメントかもしれない –

+0

私はXercesに慣れていませんが、RAIIをstd :: auto_ptrなどで試してみましたか? これを避けたいのであれば、私は通常逆順でアイテムを削除します。エラーハンドラの前にxmlParserを削除するので、xmlParserとエラーハンドラの間に何らかの不思議なやりとりが起こっている可能性があります。 – jdt141

+0

Xercesパーサはエラーハンドラを所有していないので、実際は正しい順序です。 –

答えて

1

が証拠を探ることができます...

#6 0x95c5a14b in std::terminate() 

私はあなたにこれを伝えることができますが呼び出されたときデストラクタがexceをスローするption。例外を投げるデストラクタは大きなノー・ノーです。 Xercesは何かうんざりしているかもしれません。

それとも、このライン何かが仮想関数テーブルに欠落している可能性があり

#7 0x95c5a6da in __cxa_pure_virtual() 

によって引き起こされている可能性があります。おそらくDOMオブジェクトのメンバーのデストラクタの1つですか?おそらくこれは例外を生成するでしょうか?

This linkは、仮想テーブルの参照が失敗する原因を説明しています。要するに、それは、そのポインタに対して多態的な関数呼び出しをしようとする人の周りにぶら下がっているぶら下がっている基底クラスのポインタによって引き起こされる可能性があります。

例上記のリンクから与えられた:

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

が、後で削除/

// Clean up 
    XMLString::release(&xmlMetadata); 
    xmlDoc->release(); 
    delete xmlParser; 
    delete memBufIS; 
    delete errHandler; 
をリリース:XercesDomParserあなたはNEWでオブジェクトを保持しているように見える、ダングリングポインタの

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

スピーキング

あなたが物事を破壊しようとしている順序が間違っていて、上記の問題の?それに直面しても問題は解決しませんが、それは私が実験して、物事がどのように破棄されるべきかのドキュメンテーションを二重に確認する場所です。

+1

Xercesパーサーはエラーハンドラーを所有しておらず、それらを削除しません。 –

+0

@Doug Tが例外がスローされないことを述べたので、私は質問をする前にxmlParserの削除をtry/catchブロックで試しました。 –

0

明らかにコードに間違いはありません。コード内で新しい& deleteの使用をすべて削除し、代わりにスタックベースのオブジェクトとして使用するCercesオブジェクトを作成することをお勧めします。たとえば、代わりの:

xmlParser = new XercesDOMParser(); 

使用:

XercesDOMParser xmlParser; 

のように。

+0

スタックベースのXercesDOMParserのデコンストラクタでもまだセグメンテーションが失敗しています:( –