diff --git a/CMakeLists.txt b/CMakeLists.txt index 91c61a4..4a8f91d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,8 @@ include(GNUInstallDirs) ################################ # set lib version here -set(GENERIC_LIB_VERSION "2.2.0") -set(GENERIC_LIB_SOVERSION "2") +set(GENERIC_LIB_VERSION "2.2.0") +set(GENERIC_LIB_SOVERSION "2") ################################ @@ -46,33 +46,24 @@ endif(MSVC) ################################ # Add targets -set(BUILD_STATIC_LIBS ON CACHE BOOL "Set to ON to build static libraries") -if(BUILD_STATIC_LIBS) - add_library(tinyxml2static STATIC tinyxml2.cpp tinyxml2.h) - set_target_properties(tinyxml2static PROPERTIES OUTPUT_NAME tinyxml2) -endif(BUILD_STATIC_LIBS) -add_library(tinyxml2 SHARED tinyxml2.cpp tinyxml2.h) +option(BUILD_SHARED_LIBS "build shared or static libraries" ON) +add_library(tinyxml2 tinyxml2.cpp tinyxml2.h) set_target_properties(tinyxml2 PROPERTIES COMPILE_DEFINITIONS "TINYXML2_EXPORT" VERSION "${GENERIC_LIB_VERSION}" SOVERSION "${GENERIC_LIB_SOVERSION}") -add_executable(test xmltest.cpp) -add_dependencies(test tinyxml2) -add_dependencies(test ${TARGET_DATA_COPY}) -target_link_libraries(test tinyxml2) +add_executable(xmltest xmltest.cpp) +add_dependencies(xmltest tinyxml2) +add_dependencies(xmltest ${TARGET_DATA_COPY}) +target_link_libraries(xmltest tinyxml2) -if(BUILD_STATIC_LIBS) - install(TARGETS tinyxml2 tinyxml2static - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -else(BUILD_STATIC_LIBS) - install(TARGETS tinyxml2 - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif(BUILD_STATIC_LIBS) +install(TARGETS tinyxml2 + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(FILES tinyxml2.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) foreach(p LIB INCLUDE) @@ -85,4 +76,4 @@ endforeach() configure_file(tinyxml2.pc.in tinyxml2.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/tinyxml2.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) -#add_test(test ${SAMPLE_NAME} COMMAND $) +#add_test(xmltest ${SAMPLE_NAME} COMMAND $) diff --git a/tinyxml2.cpp b/tinyxml2.cpp index 9688e5d..ef3b469 100755 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -212,12 +212,13 @@ const char* StrPair::GetStr() else { int i=0; for(; iToText() ) { - return FirstChild()->ToText()->Value(); + return FirstChild()->Value(); } return 0; } @@ -1317,7 +1318,7 @@ void XMLElement::SetText( double v ) XMLError XMLElement::QueryIntText( int* ival ) const { if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->ToText()->Value(); + const char* t = FirstChild()->Value(); if ( XMLUtil::ToInt( t, ival ) ) { return XML_SUCCESS; } @@ -1330,7 +1331,7 @@ XMLError XMLElement::QueryIntText( int* ival ) const XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const { if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->ToText()->Value(); + const char* t = FirstChild()->Value(); if ( XMLUtil::ToUnsigned( t, uval ) ) { return XML_SUCCESS; } @@ -1343,7 +1344,7 @@ XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const XMLError XMLElement::QueryBoolText( bool* bval ) const { if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->ToText()->Value(); + const char* t = FirstChild()->Value(); if ( XMLUtil::ToBool( t, bval ) ) { return XML_SUCCESS; } @@ -1356,7 +1357,7 @@ XMLError XMLElement::QueryBoolText( bool* bval ) const XMLError XMLElement::QueryDoubleText( double* dval ) const { if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->ToText()->Value(); + const char* t = FirstChild()->Value(); if ( XMLUtil::ToDouble( t, dval ) ) { return XML_SUCCESS; } @@ -1369,7 +1370,7 @@ XMLError XMLElement::QueryDoubleText( double* dval ) const XMLError XMLElement::QueryFloatText( float* fval ) const { if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->ToText()->Value(); + const char* t = FirstChild()->Value(); if ( XMLUtil::ToFloat( t, fval ) ) { return XML_SUCCESS; } @@ -1622,24 +1623,7 @@ XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) : XMLDocument::~XMLDocument() { - DeleteChildren(); - delete [] _charBuffer; - -#if 0 - _textPool.Trace( "text" ); - _elementPool.Trace( "element" ); - _commentPool.Trace( "comment" ); - _attributePool.Trace( "attribute" ); -#endif - -#ifdef DEBUG - if ( Error() == false ) { - TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); - TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); - TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); - TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); - } -#endif + Clear(); } @@ -1653,6 +1637,22 @@ void XMLDocument::Clear() delete [] _charBuffer; _charBuffer = 0; + +#if 0 + _textPool.Trace( "text" ); + _elementPool.Trace( "element" ); + _commentPool.Trace( "comment" ); + _attributePool.Trace( "attribute" ); +#endif + +#ifdef DEBUG + if ( Error() == false ) { + TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); + TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); + TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); + TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); + } +#endif } @@ -1820,6 +1820,16 @@ XMLError XMLDocument::Parse( const char* p, size_t len ) ptrdiff_t delta = p - start; // skip initial whitespace, BOM, etc. ParseDeep( _charBuffer+delta, 0 ); + if (_errorID) { + // clean up now essentially dangling memory. + // and the parse fail can put objects in the + // pools that are dead and inaccessible. + DeleteChildren(); + _elementPool.Clear(); + _attributePool.Clear(); + _textPool.Clear(); + _commentPool.Clear(); + } return _errorID; } @@ -1836,6 +1846,7 @@ void XMLDocument::Print( XMLPrinter* streamer ) const void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 ) { + TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT ); _errorID = error; _errorStr1 = str1; _errorStr2 = str2; @@ -1843,7 +1854,7 @@ void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 ) const char* XMLDocument::ErrorName() const { - TIXMLASSERT(_errorID >= 0 && _errorID < XML_ERROR_COUNT ); + TIXMLASSERT( _errorID >= 0 && _errorID < XML_ERROR_COUNT ); return _errorNames[_errorID]; } diff --git a/tinyxml2.h b/tinyxml2.h index becfffd..a911003 100755 --- a/tinyxml2.h +++ b/tinyxml2.h @@ -14,7 +14,6 @@ not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. @@ -122,9 +121,9 @@ inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) /* Versioning, past 1.0.14: http://semver.org/ */ -static const int TIXML2_MAJOR_VERSION = 2; -static const int TIXML2_MINOR_VERSION = 2; -static const int TIXML2_PATCH_VERSION = 0; +static const int TIXML2_MAJOR_VERSION = 2; +static const int TIXML2_MINOR_VERSION = 2; +static const int TIXML2_PATCH_VERSION = 0; namespace tinyxml2 { @@ -263,7 +262,7 @@ public: return _mem[i]; } - const T& PeekTop() const { + const T& PeekTop() const { TIXMLASSERT( _size > 0 ); return _mem[ _size - 1]; } @@ -319,6 +318,7 @@ public: virtual void* Alloc() = 0; virtual void Free( void* ) = 0; virtual void SetTracked() = 0; + virtual void Clear() = 0; }; @@ -331,10 +331,20 @@ class MemPoolT : public MemPool public: MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} ~MemPoolT() { + Clear(); + } + + void Clear() { // Delete the blocks. - for( int i=0; i<_blockPtrs.Size(); ++i ) { - delete _blockPtrs[i]; + while( !_blockPtrs.Empty()) { + Block* b = _blockPtrs.Pop(); + delete b; } + _root = 0; + _currentAllocs = 0; + _nAllocs = 0; + _maxAllocs = 0; + _nUntracked = 0; } virtual int ItemSize() const { @@ -367,6 +377,7 @@ public: _nUntracked++; return result; } + virtual void Free( void* mem ) { if ( !mem ) { return; @@ -482,7 +493,7 @@ public: } }; -// WARNING: must match XMLErrorNames[] +// WARNING: must match XMLDocument::_errorNames[] enum XMLError { XML_SUCCESS = 0, XML_NO_ERROR = 0, @@ -516,10 +527,8 @@ enum XMLError { class XMLUtil { public: - // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't - // correct, but simple, and usually works. static const char* SkipWhiteSpace( const char* p ) { - while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast(p) ) ) { + while( IsWhiteSpace(*p) ) { ++p; } return p; @@ -527,6 +536,9 @@ public: static char* SkipWhiteSpace( char* p ) { return const_cast( SkipWhiteSpace( const_cast(p) ) ); } + + // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't + // correct, but simple, and usually works. static bool IsWhiteSpace( char p ) { return !IsUTF8Continuation(p) && isspace( static_cast(p) ); } diff --git a/tinyxml2/tinyxml2.xcodeproj/project.pbxproj b/tinyxml2/tinyxml2.xcodeproj/project.pbxproj index cd31274..58c4fcc 100644 --- a/tinyxml2/tinyxml2.xcodeproj/project.pbxproj +++ b/tinyxml2/tinyxml2.xcodeproj/project.pbxproj @@ -96,6 +96,9 @@ /* Begin PBXProject section */ 037AE058151CCC5200E0F29F /* Project object */ = { isa = PBXProject; + attributes = { + LastUpgradeCheck = 0610; + }; buildConfigurationList = 037AE05B151CCC5200E0F29F /* Build configuration list for PBXProject "tinyxml2" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; @@ -134,6 +137,8 @@ buildSettings = { CONFIGURATION_BUILD_DIR = "$(SYMROOT)/Debug"; COPY_PHASE_STRIP = NO; + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = DEBUG; + ONLY_ACTIVE_ARCH = YES; SYMROOT = build; }; name = Debug; @@ -156,6 +161,7 @@ GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; INSTALL_PATH = /usr/local/bin; + MACOSX_DEPLOYMENT_TARGET = ""; PREBINDING = NO; PRODUCT_NAME = xmltest; }; @@ -171,6 +177,7 @@ GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; + MACOSX_DEPLOYMENT_TARGET = ""; PREBINDING = NO; PRODUCT_NAME = tinyxml2; ZERO_LINK = NO; diff --git a/xmltest.cpp b/xmltest.cpp index d3508ab..805b3ce 100644 --- a/xmltest.cpp +++ b/xmltest.cpp @@ -279,6 +279,8 @@ int main( int argc, const char ** argv ) { #if defined( _MSC_VER ) && defined( DEBUG ) _CrtMemCheckpoint( &startMemState ); + // Enable MS Visual C++ debug heap memory leaks dump on exit + _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); #endif #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__) @@ -1371,7 +1373,22 @@ int main( int argc, const char ** argv ) */ } #endif - + + { + // Issue #184 + // If it doesn't assert, it passes. Caused by objects + // getting created during parsing which are then + // inaccessible in the memory pools. + { + XMLDocument doc; + doc.Parse(""); + } + { + XMLDocument doc; + doc.Parse(""); + doc.Clear(); + } + } // ----------- Performance tracking --------------