3

私はXerces-CXMLライブラリをいじっています。

私が遊んでいるこの簡単な例があります。

メモリリークやセグフォールトなしで実行することはできないようです。それはどちらかです。

「クリーンアップ」でパーサーオブジェクトを削除すると、常にセグメンテーション違反が発生します。

ライブラリの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;
}
4

3 に答える 3

9

"xmlDoc-> release();"が原因です。「xmlParser->adoptDocument()」と言わない限り、そのノードを所有することはできません。

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

于 2009-06-07T03:16:22.427 に答える
1

証拠を探りましょう...

#6  0x95c5a14b in std::terminate ()

これは、デストラクタが例外をスローしたときに呼び出されると言えます。例外をスローするデストラクタは大したことではありません。Xercesは何かおかしなことをしているのかもしれません。

または、この行が原因である可能性があります

#7  0x95c5a6da in __cxa_pure_virtual ()

仮想関数テーブルで何かが欠落している可能性がある場所。おそらく、DOMオブジェクトのメンバーデストラクタの1つですか?おそらくこれは例外を生成しますか?

このリンクは、仮想テーブルのルックアップが失敗する原因についての優れた説明を提供します。要するに、それは、そのポインターでポリモーフィック関数呼び出しを行おうとしている誰かの周りにぶら下がっている基本クラスのポインターによって引き起こされる可能性があります。

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

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

あなたが物事を破壊している順序が間違っていて、上記の問題のいくつかを引き起こす可能性がありますか?一見、物事は大丈夫に見えますが、そこで私は実験して、物事がどのように取り壊されることになっているのかについてのドキュメントを再確認します。

于 2009-06-06T17:49:16.663 に答える
0

コードに明らかに問題があることはわかりません。コード内のnew&deleteの使用をすべて削除し、代わりにスタックベースのオブジェクトとして使用するCercesオブジェクトを作成してみてください。たとえば、次の代わりに:

xmlParser = new XercesDOMParser();

使用する:

XercesDOMParser xmlParser;

等々。

于 2009-06-06T18:07:38.130 に答える