2009-06-06 53 views
3

我一直在玩Xerces-C XML庫。Xerces-C問題;段錯誤調用對象析構函數

我有我玩這個簡單的例子。

我似乎無法讓它運行,沒有泄漏內存和沒有segfaulting。 它是一個或另一個。

當我在「清理」下刪除解析器對象時,總會發生段錯誤。

我已經嘗試使用2.8版本的庫文件的2.8 &。

注意:我把所有的異常檢查都拿出來了,我得到了和它一樣的結果。爲了便於閱讀和簡單,我從下面的代碼中刪除了它。

在那裏的任何Xerces精明的人都在意提出一些建議嗎?

我真的不能從後面的跟蹤中知道多少,它只是跳到超類析構函數中,並在那裏進行segfaulting。

回溯:

(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。也許像「//死在這裏」這樣的行尾註釋? – 2009-06-06 17:48:12

+0

所以我不熟悉Xerces,但是你有沒有試過用RAII和std :: auto_ptr或類似的東西? 如果你想避免這種情況,我通常會以相反的順序刪除它們。在xmlParser和錯誤處理程序之間可能會發生一些奇怪的交互,因爲您在errorHandler之前刪除了xmlParser? – jdt141 2009-06-06 17:52:01

+0

Xerces解析器不擁有它們的錯誤處理程序,所以這實際上是正確的順序。 – 2009-06-06 18:12:59

回答

1

讓我們探討證據......

#6 0x95c5a14b in std::terminate() 

我可以告訴你,這就是所謂的當析構函數拋出一個exce ption。析構函數拋出異常是一個很大的禁忌。 Xerces可能會做些不可思議的事情。

或者它可能通過這條線

#7 0x95c5a6da in __cxa_pure_virtual() 

,其中一些可能會在虛函數表中丟失引起的。也許DOM對象的成員析構函數之一?也許這會產生一個異常?

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

來說,它看起來像XercesDomParser持有的對象,你newed:

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

但後來刪除/發佈

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

請問您的訂單是不是正在銷燬東西,並導致一些以上問題?從表面上看,事情看起來還不錯,但這正是我要試驗的地方,並仔細檢查文件應該如何被拆除。

0

我看不出任何明顯的代碼錯誤。您可能想嘗試刪除代碼中新的&刪除的所有用法,並創建您用作基於堆棧的對象的Cerces對象。例如,而不是:

xmlParser = new XercesDOMParser(); 

使用:

XercesDOMParser xmlParser; 

等。

相關問題