Statisches Attribut sorgt für Segmentation Fault vor (!) der Main



  • Hallo,

    beim Erstellen eines geeigneten Parsers mit der Apache Xerces Bibliothek (SAX) für ein bestimmtes XML-Format ist mir eine bisher noch nicht begegnete Eigenart in C++ (oder gar Xerces?) untergekommen. Wenn ich Attribute des Typs XercesString (Entnommen aus http://www.ibm.com/developerworks/xml/library/x-xercc/) in meinem eigenen Handler (erbt von der Xerces-Klasse "DefaultHandler") als statisch deklariere, erhalte ich nach erfolgreichem Kompilieren und Starten einen Segmentation Fault, der vor (!) der Main-Funktion auftritt. Sinn des Ganzen soll eine Optimierung des Codes sein. Jedenfalls funktionieren diese Attribute als nicht-statische Elemente der Klasse einwandfrei. Richtig deklariert und vor allem initialisiert sollten diese statischen Attribute sein. Jedenfalls geht es ohne Weiteres mit dem Typ std::string aus der STL. Wie kann es also sein, dass ein einzelnes statisches Attribut einen solch fatalen Fehler auslöst?

    Ich bin dankbar für jede Antwort! 😃

    #ifndef XERCESSTRING_H_
    #define XERCESSTRING_H_
    
    #include <util/XMLString.hpp>
    
    namespace Utils {
    
    namespace String {
    
    #ifdef XERCES_CPP_NAMESPACE_USE
    XERCES_CPP_NAMESPACE_USE
    #endif
    
    class XercesString
    {
    	XMLCh *_wstr;
    public:
    	XercesString() : _wstr(0L) { };
    	XercesString(const char *str);
    	XercesString(XMLCh *wstr);
    	XercesString(const XMLCh *wstr);
    	XercesString(const XercesString &copy);
    	~XercesString();
    	bool append(const XMLCh *tail);
    	bool erase(const XMLCh *head, const XMLCh *tail);
    	const XMLCh* begin() const;
    	const XMLCh* end() const;
    	int size() const;
    	XMLCh & operator [] (const int i);
    	const XMLCh operator [] (const int i) const;
    	operator const XMLCh * () const { return _wstr; };
    	void operator = (const char *str) { _wstr = XMLString::transcode(str); }
    };
    
    }
    
    }
    
    #endif /* XERCESSTRING_H_ */
    
    #include "XercesString.h"
    
    namespace Utils {
    
    namespace String {
    
    	XercesString::XercesString(const char *str) : _wstr(NULL)
    	{
    	  _wstr = XMLString::transcode(str);
    	}
    
    	XercesString::XercesString(XMLCh *wstr) : _wstr(wstr) { };
    
    	XercesString::XercesString(const XMLCh *wstr) : _wstr(NULL)
    	{
    	  _wstr = XMLString::replicate(wstr);
    	}
    
    	XercesString::XercesString(const XercesString &right) : _wstr(NULL)
    	{
    	  _wstr = XMLString::replicate(right._wstr);
    	}
    
    	XercesString::~XercesString()
    	{
    	  // thanks tinny!!
    	  if (_wstr) XMLString::release(&_wstr);
    	}
    
    	bool XercesString::append(const XMLCh *tail)
    	{
    	  int iTailLen = XMLString::stringLen(tail);
    	  int iWorkLen = XMLString::stringLen(_wstr);
    	  XMLCh *result = new XMLCh[ iWorkLen + iTailLen + 1 ];
    	  bool bOK = result != NULL;
    	  if (bOK)
    	  {
    		XMLCh *target = result;
    		XMLString::moveChars(target, _wstr, iWorkLen);
    		target += iWorkLen;
    		XMLString::moveChars(target, tail, iTailLen);
    		target += iTailLen;
    		*target++ = 0;
    		XMLString::release(&_wstr);
    		_wstr = result;
    	  }
    	  return bOK;
    	}
    
    	bool XercesString::erase(const XMLCh *head, const XMLCh *tail)
    	{
    	  bool bOK = head <= tail && head >= begin() && tail <= end();
    	  if (bOK)
    	  {
    		XMLCh *result = new XMLCh[ size() - (tail - head) + 1 ];
    		XMLCh *target = result;
    		bOK = target != NULL;
    		if (bOK)
    		{
    		  const XMLCh *cursor = begin();
    
    		  while (cursor != head) *target++ = *cursor++;
    		  cursor = tail;
    		  while ( cursor != end() ) *target++ = *cursor++;
    		  *target ++ = 0;
    		  XMLString::release(&_wstr);
    		  _wstr = result;
    		}
    	  }
    	  return bOK;
    	}
    
    	const XMLCh* XercesString::begin() const
    	{
    	  return _wstr;
    	}
    
    	const XMLCh* XercesString::end() const
    	{
    	  return _wstr + size();
    	}
    
    	int XercesString::size() const
    	{
    	  return XMLString::stringLen(_wstr);
    	}
    
    	XMLCh & XercesString::operator [] (const int i)
    	{
    	  return _wstr[i];
    	}
    
    	const XMLCh XercesString::operator [] (const int i) const
    	{
    	  return _wstr[i];
    	}
    
    }
    
    }
    
    #ifndef UNITHANDLER_H_
    #define UNITHANDLER_H_
    
    #include <SFML/Graphics.hpp>
    #include <SFML/Audio/Sound.hpp>
    
    #include <sax2/DefaultHandler.hpp>
    
    #include <boost/shared_ptr.hpp>
    
    #include <cstdlib>
    #include <string>
    #include <map>
    
    #include "../Graphics/AnimatedSprite.h"
    #include "../Utils/String/XercesString.h"
    
    #ifdef XERCES_CPP_NAMESPACE_USE
    XERCES_CPP_NAMESPACE_USE
    #endif
    
    using namespace Engine::Graphics;
    
    using namespace Utils::String; /* XercesString */
    
    namespace Engine {
    
    namespace Serialization {
    
    /*
     * An instance of the structure sprite_set contains sprites of
     * a specified action of the unit including all sub sprites like
     * holding a weapon.
     */
    struct action_set
    {
    	std::string m_strAction;
    
    	sf::Image m_image;
    	sf::Sound m_sound;
    
    	std::map<std::string, AnimatedSprite> m_sprites;
    
    	action_set(std::string& strAction) : m_strAction(strAction) { };
    	action_set() { };
    	AnimatedSprite* operator[](std::string spriteKey) { return &m_sprites[spriteKey]; };
    };
    
    /*
     * An instance of the UnitHandler provides methods for filling
     * a unit using a XML file as source. Its mostly used by an in-
     * stance of SAX2XMLReader.
     */
    class UnitHandler : public DefaultHandler
    {
    private:
    	/*
    	 * Debug mode on/off
    	 */
    	static const bool m_bDebug = true;
    
    	/* Tags */
    
    	static std::string m_strTest;
    
    	/* Folgendes Attribut würde den besagten Fehler auslösen */
    	static const XercesString m_tstrActions;
    
    	XercesString m_tstrAction;
    	XercesString m_tstrSprite;
    	XercesString m_tstrStart;
    	XercesString m_tstrRun;
    	XercesString m_tstrStop;
    	XercesString m_tstrFrame;
    
    	/* Attributes */
    	XercesString m_astrName;
    	XercesString m_astrLow;
    	XercesString m_astrNormal;
    	XercesString m_astrHigh;
    	XercesString m_astrSound;
    	XercesString m_astrLeft;
    	XercesString m_astrTop;
    	XercesString m_astrRight;
    	XercesString m_astrBottom;
    	XercesString m_astrDelay;
    
    	std::map<std::string, action_set>* m_pActions;
    
    	std::map<std::string, action_set>::iterator m_ActionsIterator;
    
    	std::map<std::string, AnimatedSprite>::iterator m_SpriteIterator;
    
    	boost::shared_ptr< std::vector<Frame> > m_pTmpFrames;
    
    	bool m_bUsePhysFS;
    
    	/*
    	 * Boolean variables used by the XML Parser
    	 */
    	bool m_bFile;
    public:
    	/*
    	 * Creates a new instance of UnitHandler using a given unit as
    	 * argument. The given unit will be filled with data (for example
    	 * sprites) using a xml file as source.
    	 */
    	UnitHandler(std::map<std::string, action_set>& actions, bool usePhysFS);
    	virtual ~UnitHandler();
    
    	virtual void startDocument();
    	virtual void endDocument();
    
    	virtual void startElement(
    	const XMLCh* const uri,
    	const XMLCh* const localname,
    	const XMLCh* const qname,
    	const Attributes& attrs);
    
    	virtual void endElement(
    	const XMLCh* const uri,
    	const XMLCh* const localname,
    	const XMLCh* const qname);
    
    	virtual void characters(
    	const XMLCh* const chars,
    	const unsigned int length);
    
    };
    
    }
    
    }
    
    #endif /* UNITHANDLER_H_ */
    
    #include "UnitHandler.h"
    #include <sax2/Attributes.hpp>
    
    #include "../Utils/String/XercesString.h"
    
    namespace Engine {
    
    namespace Serialization {
    
    	/* Initialisierung des Attributes, welches den Fehler auslöst */
    	const XercesString UnitHandler::m_tstrActions("actions");
    
    	UnitHandler::UnitHandler(std::map<std::string, action_set>& actions, bool usePhysFS) : m_pActions(&actions), m_bUsePhysFS(usePhysFS) {
    
    		//m_tstrActions = "actions";
    		m_tstrAction = "action";
    		m_tstrSprite = "sprite";
    		m_tstrStart = "start";
    		m_tstrRun = "run";
    		m_tstrStop = "stop";
    		m_tstrFrame = "frame";
    		m_astrName = "name";
    		m_astrLow = "low";
    		m_astrNormal = "normal";
    		m_astrHigh = "high";
    		m_astrSound = "sound";
    		m_astrLeft = "left";
    		m_astrTop = "top";
    		m_astrRight = "right";
    		m_astrBottom = "bottom";
    		m_astrDelay = "delay";
    
    	}
    
    	UnitHandler::~UnitHandler() {
    
    	}
    
    	void UnitHandler::startDocument()
    	{
    		if(m_bDebug) std::cout << "_start document_" << std::endl;
    	}
    
    	void UnitHandler::endDocument()
    	{
    		if(m_bDebug) std::cout << "_end document_" << std::endl;
    	}
    
    	void UnitHandler::startElement(const XMLCh *const uri, const XMLCh *const localname, const XMLCh *const qname, const Attributes & attrs)
    	{
    		if(m_bDebug) std::cout << "__start Element__" << std::endl;
    
    		try
    		{
    			if(!XMLString::compareString(localname, m_tstrAction))
    			{
    				std::string strName(XMLString::transcode(attrs.getValue(m_astrName)));
    				std::string strImage(XMLString::transcode(attrs.getValue(m_astrLow)));
    
    				m_pActions->insert(std::make_pair(strName, action_set(strName)));
    				m_ActionsIterator = m_pActions->find(strName);
    
    				if(m_bUsePhysFS){
    					/* Load image using physicsFS [NOT IMPLEMENTED]*/
    				}
    				else
    				{
    					m_ActionsIterator->second.m_image.LoadFromFile(strImage);
    					m_ActionsIterator->second.m_image.CreateMaskFromColor(sf::Color(255,0,255,255), 0);
    				}
    			}
    			else if(m_pActions->size())
    			{
    				if(!XMLString::compareString(localname, m_tstrSprite))
    				{
    					std::string strName(XMLString::transcode(attrs.getValue(m_astrName)));
    					m_ActionsIterator->second.m_sprites.insert(std::make_pair(strName, AnimatedSprite()));
    					m_SpriteIterator = m_ActionsIterator->second.m_sprites.find(strName);
    					m_SpriteIterator->second.SetImage(m_ActionsIterator->second.m_image);
    				}
    				else if(!XMLString::compareString(localname, m_tstrRun))
    				{
    					boost::shared_ptr< std::vector<Frame> > pFrames(new std::vector<Frame>());
    					m_pTmpFrames = pFrames;
    				}
    				else if(!XMLString::compareString(localname, m_tstrFrame))
    				{
    					std::string strLeft(XMLString::transcode(attrs.getValue(m_astrLeft)));
    					std::string strTop(XMLString::transcode(attrs.getValue(m_astrTop)));
    					std::string strRight(XMLString::transcode(attrs.getValue(m_astrRight)));
    					std::string strBottom(XMLString::transcode(attrs.getValue(m_astrBottom)));
    					std::string strDelay(XMLString::transcode(attrs.getValue(m_astrDelay)));
    
    					m_pTmpFrames->push_back(Frame(IntRect(atoi(strLeft.c_str()),
    														  atoi(strTop.c_str()),
    														  atoi(strRight.c_str()),
    														  atoi(strBottom.c_str())), static_cast<float>(atof(strDelay.c_str()))));
    				}
    			}
    		}
    		catch(std::exception &e)
    		{
    			std::cerr << "Caught " << e.what() << std::endl;
    		}
    
    	}
    
    	void UnitHandler::characters(const XMLCh *const chars, const unsigned int length)
    	{
    		if(m_bDebug) std::cout << "___characters___" << std::endl;
    	}
    
    	void UnitHandler::endElement(const XMLCh *const uri, const XMLCh *const localname, const XMLCh *const qname)
    	{
    		if(m_bDebug) std::cout << "__end Element__" << std::endl;
    
    		if(!XMLString::compareString(localname, m_tstrRun))
    		{
    			m_SpriteIterator->second.SetSubRectangles(m_pTmpFrames);
    		}
    	}
    
    }
    
    }
    


  • bisschen weniger quellcode, diesen dann kommentiert....



  • Was macht XMLString::transcode? Hast du mal einen Backtrace gemacht wo genau der Segfault kommt? Abgesehen davon bin ich mit Skybrabbel einer Meinung, kürz den Code mal auf das Wesentliche.


Anmelden zum Antworten