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."
This commit is contained in:
@@ -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_;
|
||||
|
||||
@@ -354,6 +354,8 @@ namespace osgIntrospection
|
||||
/// this method, for example NoDefaultValueAttribute.
|
||||
Value getDefaultValue() const;
|
||||
|
||||
virtual ~PropertyInfo() {};
|
||||
|
||||
protected:
|
||||
virtual void getInheritedProviders(CustomAttributeProviderList& providers) const;
|
||||
|
||||
|
||||
@@ -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<typename C> friend class Reflector;
|
||||
template<typename C> friend struct TypeNameAliasProxy;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -113,12 +113,10 @@ Type* Reflection::getOrRegisterType(const ExtendedTypeInfo &ti, bool replace_if_
|
||||
std::string old_namespace = i->second->getNamespace();
|
||||
std::vector<std::string> 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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user