Xerces-C 문제; 객체 소멸자 호출에 대한 segfault
-
12-09-2019 - |
문제
나는 함께 놀았다 Xerces-C XML 라이브러리.
나는 내가 가지고 놀고있는이 간단한 예제가있다.
메모리를 누출하지 않고 Segfaulting없이 실행할 수없는 것 같습니다. 하나 또는 다른 것입니다.
Segfault는 항상 "Clean Up"에서 파서 객체를 삭제할 때 항상 발생합니다.
라이브러리의 2.8 및 2.7 버전을 모두 사용해 보았습니다.
메모: 나는 코드에서 체크 아웃하는 모든 예외를 가져 갔다. 나는 그것과 동일한 결과를 얻지 못했다. 가독성과 단순성을 위해 아래 코드에서 제거했습니다.
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;
}
해결책
"xmldoc-> release ();"는 범인입니다. "XMLPARSER-> ANDICALTDOCUMENT ()"라고 말하지 않는 한 해당 노드를 소유하지 않습니다.
다른 팁
증거를 탐구합시다 ...
#6 0x95c5a14b in std::terminate ()
소멸자가 예외를 던질 때 이것이 호출되었다고 말할 수 있습니다. 예외를 던지는 소멸자는 큰 금지입니다. Xerces는 Winky를하고있을 수 있습니다.
또는이 라인으로 인해 발생할 수 있습니다
#7 0x95c5a6da in __cxa_pure_virtual ()
가상 함수 테이블에서 무언가가 누락 될 수있는 곳. 아마도 DOM Object의 멤버 파괴자 중 하나인가? 아마도 이것은 예외를 생성합니까?
이 링크 가상 테이블 조회가 실패 할 수있는 원인에 대한 훌륭한 설명을 제공합니다. 요컨대, 그것은 그 포인터에 다형성 기능을 호출하려고하는 누군가 주위에 매달려있는 기본 클래스 포인터로 인해 발생할 수 있습니다.
위의 링크에서 제공된 예 :
// 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의 모든 용도를 제거하고 대신 스택 기반 Objectys로 사용하는 CERCES 객체를 만들려고 할 수 있습니다. 예를 들어 : 대신 :
xmlParser = new XercesDOMParser();
사용:
XercesDOMParser xmlParser;
등등.