From 3c2872a36a1151f267e9414e24d5367fb312a107 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 25 Feb 2008 16:26:30 +0000 Subject: [PATCH] From Emmanuel Roche, "I'm joining two zip files to this mail for the modified sources and include files of osgIntrospection. The modifications I made are very small but they are absolutely usefull to use osgIntrospection with visual studio 7.1 or 8 in debug modes. This should also solve other minor common problems (converter memory leak, virtual destructor for PropertyInfo, etc...). I choosed two function names : Reflection::uninitialize() and Type::reset(), this can of course be changed if someone has a better idea... I made the changes against OSG 2.2.0 public release. I tested the result with VS 7.1, VS 7.1 SP1, VS 8.0 SP1 and AQTime 5.0 on Windows XP SP2... All 4 seem to agree : they detected memory leaks before and don't anymore. Sorry I haven't take the time to test that on linux but the changes are so small I doubt there could be a problem... I let you check that on your side :-). I hope this will help making OSG an even more wonderfull library." --- .../osgIntrospection/CustomAttributeProvider | 6 ++++- include/osgIntrospection/PropertyInfo | 2 ++ include/osgIntrospection/Reflection | 5 ++++ include/osgIntrospection/Type | 4 +++ src/osgIntrospection/Reflection.cpp | 25 ++++++++++++++----- src/osgIntrospection/Type.cpp | 19 ++++++++++++-- 6 files changed, 52 insertions(+), 9 deletions(-) diff --git a/include/osgIntrospection/CustomAttributeProvider b/include/osgIntrospection/CustomAttributeProvider index 228482bea..f3c7825b4 100644 --- a/include/osgIntrospection/CustomAttributeProvider +++ b/include/osgIntrospection/CustomAttributeProvider @@ -115,7 +115,11 @@ namespace osgIntrospection protected: virtual void getInheritedProviders(CustomAttributeProviderList& providers) const = 0; - virtual ~CustomAttributeProvider() {} + virtual ~CustomAttributeProvider() { + for(CustomAttributeList::iterator it = attribs_.begin(); it != attribs_.end(); ++it) { + delete (*it); + } + } private: CustomAttributeList attribs_; diff --git a/include/osgIntrospection/PropertyInfo b/include/osgIntrospection/PropertyInfo index b12e3db10..f153195e6 100644 --- a/include/osgIntrospection/PropertyInfo +++ b/include/osgIntrospection/PropertyInfo @@ -354,6 +354,8 @@ namespace osgIntrospection /// this method, for example NoDefaultValueAttribute. Value getDefaultValue() const; + virtual ~PropertyInfo() {}; + protected: virtual void getInheritedProviders(CustomAttributeProviderList& providers) const; diff --git a/include/osgIntrospection/Reflection b/include/osgIntrospection/Reflection index 91a6bf8f7..4082b2fdf 100644 --- a/include/osgIntrospection/Reflection +++ b/include/osgIntrospection/Reflection @@ -79,6 +79,11 @@ namespace osgIntrospection static const Converter* getConverter(const Type& source, const Type& dest); static bool getConversionPath(const Type& source, const Type& dest, ConverterList& conv); + // This function should be called (at least on windows platforms using Visual Studio 7.1 or 8 as compiler) to unregister + // all the known types before exiting your program: otherwise, you will get a lot of false positive memory leaks in debug builds. + // It might also be used to dynamically reload the description of the known types (?) + static void uninitialize(); + private: template friend class Reflector; template friend struct TypeNameAliasProxy; diff --git a/include/osgIntrospection/Type b/include/osgIntrospection/Type index 359e24c65..c9a73d893 100644 --- a/include/osgIntrospection/Type +++ b/include/osgIntrospection/Type @@ -253,6 +253,10 @@ namespace osgIntrospection Value createInstance(ValueList& args) const; inline Value createInstance() const; + // This function is called internally to reset all the elements contained in that type. + // used in the type loading process: it solves a false positive issue on VS 7.1 and 8 compilers in debug builds. + void reset(); + protected: Type(const ExtendedTypeInfo &ti) : _ti(ti), diff --git a/src/osgIntrospection/Reflection.cpp b/src/osgIntrospection/Reflection.cpp index 72f752f7f..521fc0217 100644 --- a/src/osgIntrospection/Reflection.cpp +++ b/src/osgIntrospection/Reflection.cpp @@ -113,12 +113,10 @@ Type* Reflection::getOrRegisterType(const ExtendedTypeInfo &ti, bool replace_if_ std::string old_namespace = i->second->getNamespace(); std::vector old_aliases = i->second->_aliases; - Type* newtype = new (i->second) Type(ti); - newtype->_name = old_name; - newtype->_namespace = old_namespace; - newtype->_aliases.swap(old_aliases); - - return newtype; + i->second->reset(); + i->second->_name = old_name; + i->second->_namespace = old_namespace; + i->second->_aliases.swap(old_aliases); } return i->second; } @@ -128,7 +126,16 @@ Type* Reflection::getOrRegisterType(const ExtendedTypeInfo &ti, bool replace_if_ void Reflection::registerConverter(const Type& source, const Type& dest, const Converter* cvt) { + const Converter* old = NULL; + StaticData::ConverterMap::iterator it = getOrCreateStaticData().convmap[&source].find(&dest); + + if(it != getOrCreateStaticData().convmap[&source].end()) + old = it->second; + getOrCreateStaticData().convmap[&source][&dest] = cvt; + + if(old) + delete old; } const Converter* Reflection::getConverter(const Type& source, const Type& dest) @@ -196,3 +203,9 @@ bool Reflection::accum_conv_path(const Type& source, const Type& dest, Converter return false; } + +void Reflection::uninitialize() { + if(_static_data) + delete _static_data; + _static_data = 0; +} diff --git a/src/osgIntrospection/Type.cpp b/src/osgIntrospection/Type.cpp index 61c6402eb..a7ad7dd5b 100644 --- a/src/osgIntrospection/Type.cpp +++ b/src/osgIntrospection/Type.cpp @@ -51,19 +51,34 @@ namespace } -Type::~Type() -{ +void Type::reset() +{ for (PropertyInfoList::const_iterator i=_props.begin(); i!=_props.end(); ++i) delete *i; for (MethodInfoList::const_iterator i=_methods.begin(); i!=_methods.end(); ++i) delete *i; + for (MethodInfoList::const_iterator i=_protected_methods.begin(); i!=_protected_methods.end(); ++i) + delete *i; for (ConstructorInfoList::const_iterator i=_cons.begin(); i!=_cons.end(); ++i) delete *i; + for (ConstructorInfoList::const_iterator i=_protected_cons.begin(); i!=_protected_cons.end(); ++i) + delete *i; + + _props.clear(); + _methods.clear(); + _protected_methods.clear(); + _cons.clear(); + _protected_cons.clear(); delete _rw; delete _cmp; } +Type::~Type() +{ + reset(); +} + bool Type::isSubclassOf(const Type& type) const { check_defined();