From e5c793dbdf87e838bb2b60c6a5905ced0e5548f9 Mon Sep 17 00:00:00 2001 From: "David C. Lonie" Date: Tue, 27 Sep 2016 11:37:19 -0400 Subject: [PATCH 1/3] Refactor vtkDebugLeaks construction. vtkDebugLeaks registers instance by class name, which worked well for many years. However, now that we have more templated code, this is becoming difficult. For instance, "template vtkBuffer" would be identified as "vtkBuffer" when registering with vtkDebugLeaks, but deregistered with the compiler dependent typeid(vtkBuffer).name() string returned from GetClassName(). This patch moves vtkDebugLeaks registrations to the method vtkObjectBase::InitializeObjectBase(), which must be called after the vtkObjectBase is instantiated. This ensures that objects are registered using the same string as when they are destroyed. In general, a call to "new vtkSomeClass" must be followed by a call to InitializeObjectBase on the new instance. The common ::New() implementation macros in vtkObjectFactory will ensure that registration happens correctly. Two notable exceptions are vtkCommand and vtkInformationKey subclasses. These do not require any specific handling for vtkDebugLeaks registration. See discussion at: http://vtk.1045678.n5.nabble.com/Proposal-Simplify-vtkDebugLeaks-registration-td5740222.html --- .../Testing/Cxx/TestDataArrayIterators.cxx | 2 +- .../Core/Testing/Cxx/TestGarbageCollector.cxx | 14 +++---- Common/Core/Testing/Cxx/TestObjectFactory.cxx | 19 +++++---- Common/Core/vtkDebugLeaks.h | 42 ++++++++++++++----- Common/Core/vtkDenseArray.txx | 13 +++--- Common/Core/vtkDynamicLoader.cxx | 6 +-- Common/Core/vtkIndent.cxx | 9 +--- Common/Core/vtkInformationDoubleKey.cxx | 2 +- Common/Core/vtkInformationDoubleVectorKey.cxx | 2 +- Common/Core/vtkInformationIdTypeKey.cxx | 2 +- Common/Core/vtkInformationIntegerKey.cxx | 2 +- .../Core/vtkInformationIntegerPointerKey.cxx | 2 +- .../Core/vtkInformationIntegerVectorKey.cxx | 2 +- Common/Core/vtkInformationKey.cxx | 7 ---- Common/Core/vtkInformationKeyVectorKey.cxx | 5 +-- .../vtkInformationObjectBaseVectorKey.cxx | 2 +- Common/Core/vtkInformationStringKey.cxx | 2 +- Common/Core/vtkInformationStringVectorKey.cxx | 2 +- Common/Core/vtkInformationUnsignedLongKey.cxx | 2 +- Common/Core/vtkInformationVariantKey.cxx | 2 +- .../Core/vtkInformationVariantVectorKey.cxx | 2 +- Common/Core/vtkMath.cxx | 8 ++-- Common/Core/vtkObject.cxx | 8 ++-- Common/Core/vtkObjectBase.cxx | 8 ++++ Common/Core/vtkObjectBase.h | 15 ++++++- Common/Core/vtkObjectFactory.cxx | 20 ++------- Common/Core/vtkObjectFactory.h | 21 +++++----- Common/Core/vtkObjectFactoryCollection.cxx | 12 +++--- Common/Core/vtkOutputWindow.cxx | 10 +---- Common/Core/vtkPoints.cxx | 4 +- Common/Core/vtkPoints2D.cxx | 4 +- Common/Core/vtkSparseArray.txx | 11 +++-- Common/DataModel/vtkHyperOctree.cxx | 30 ++++--------- Common/DataModel/vtkHyperTree.cxx | 13 +++--- ...ionQuadratureSchemeDefinitionVectorKey.cxx | 2 +- .../TestThreadedImageAlgorithmSplitExtent.cxx | 6 +-- .../vtkInformationExecutivePortKey.cxx | 2 +- .../vtkInformationExecutivePortVectorKey.cxx | 2 +- .../vtkThreadedCompositeDataPipeline.cxx | 10 ++--- Common/System/vtkDirectory.cxx | 11 +---- Common/Transforms/vtkAbstractTransform.cxx | 7 +--- IO/Core/vtkGlobFileNames.cxx | 6 +-- IO/Infovis/vtkPhyloXMLTreeReader.cxx | 10 ++--- .../Testing/Cxx/TestLegacyArrayMetaData.cxx | 16 +++---- IO/XML/Testing/Cxx/TestDataObjectXMLIO.cxx | 16 +++---- Parallel/MPI/vtkMPIController.cxx | 1 + Rendering/Core/vtkGraphicsFactory.cxx | 6 --- Rendering/Core/vtkRenderWindowInteractor.cxx | 8 ++-- Rendering/Core/vtkTextRenderer.cxx | 13 +----- Rendering/FreeType/vtkFreeTypeTools.cxx | 1 + Rendering/FreeType/vtkMathTextUtilities.cxx | 12 +----- 51 files changed, 192 insertions(+), 242 deletions(-) diff --git a/Common/Core/Testing/Cxx/TestDataArrayIterators.cxx b/Common/Core/Testing/Cxx/TestDataArrayIterators.cxx index 73506574872..4edd3f66dd5 100644 --- a/Common/Core/Testing/Cxx/TestDataArrayIterators.cxx +++ b/Common/Core/Testing/Cxx/TestDataArrayIterators.cxx @@ -33,7 +33,7 @@ class MyArray : public vtkTypedDataArray vtkFloatArray *Data; public: vtkTypeMacro(MyArray, vtkTypedDataArray) - static MyArray *New() { return new MyArray; } + static MyArray *New() { VTK_STANDARD_NEW_BODY(MyArray) } void Init(vtkFloatArray *array) { this->Data = array; diff --git a/Common/Core/Testing/Cxx/TestGarbageCollector.cxx b/Common/Core/Testing/Cxx/TestGarbageCollector.cxx index 3b4e43aea4a..2880a9698ec 100644 --- a/Common/Core/Testing/Cxx/TestGarbageCollector.cxx +++ b/Common/Core/Testing/Cxx/TestGarbageCollector.cxx @@ -24,7 +24,12 @@ class vtkTestReferenceLoop: public vtkObject { public: - static vtkTestReferenceLoop* New() { return new vtkTestReferenceLoop; } + static vtkTestReferenceLoop* New() + { + vtkTestReferenceLoop *ret = new vtkTestReferenceLoop; + ret->InitializeObjectBase(); + return ret; + } vtkTypeMacro(vtkTestReferenceLoop, vtkObject); void Register(vtkObjectBase* o) VTK_OVERRIDE { this->RegisterInternal(o, 1); } @@ -34,17 +39,12 @@ class vtkTestReferenceLoop: public vtkObject vtkTestReferenceLoop() { this->Other = new vtkTestReferenceLoop(this); -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::ConstructClass("vtkTestReferenceLoop"); -#endif + this->Other->InitializeObjectBase(); } vtkTestReferenceLoop(vtkTestReferenceLoop* other) { this->Other = other; this->Other->Register(this); -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::ConstructClass("vtkTestReferenceLoop"); -#endif } ~vtkTestReferenceLoop() VTK_OVERRIDE { diff --git a/Common/Core/Testing/Cxx/TestObjectFactory.cxx b/Common/Core/Testing/Cxx/TestObjectFactory.cxx index b183a719dbc..2fcd66f9a0b 100644 --- a/Common/Core/Testing/Cxx/TestObjectFactory.cxx +++ b/Common/Core/Testing/Cxx/TestObjectFactory.cxx @@ -33,7 +33,7 @@ class vtkTestPoints : public vtkPoints } vtkTypeMacro(vtkTestPoints,vtkPoints); - static vtkTestPoints* New() { return new vtkTestPoints; } + static vtkTestPoints* New() { VTK_STANDARD_NEW_BODY(vtkTestPoints) } vtkTestPoints() { } private: vtkTestPoints(const vtkTestPoints&); @@ -50,7 +50,7 @@ class vtkTestPoints2 : public vtkPoints // Methods from vtkObject vtkTypeMacro(vtkTestPoints2,vtkPoints); - static vtkTestPoints2* New() { return new vtkTestPoints2; } + static vtkTestPoints2* New() { VTK_STANDARD_NEW_BODY(vtkTestPoints2) } vtkTestPoints2() { } private: vtkTestPoints2(const vtkTestPoints2&); @@ -65,7 +65,12 @@ class VTK_EXPORT TestFactory : public vtkObjectFactory { public: TestFactory(); - static TestFactory* New() { return new TestFactory;} + static TestFactory* New() + { + TestFactory *f = new TestFactory; + f->InitializeObjectBase(); + return f; + } const char* GetVTKSourceVersion() VTK_OVERRIDE { return VTK_SOURCE_VERSION; } const char* GetDescription() VTK_OVERRIDE { return "A fine Test Factory"; } @@ -74,11 +79,6 @@ class VTK_EXPORT TestFactory : public vtkObjectFactory void operator=(const TestFactory&); }; - - - - - TestFactory::TestFactory() { this->RegisterOverride("vtkPoints", @@ -97,7 +97,8 @@ void TestNewPoints(vtkPoints* v, const char* expectedClassName) if(strcmp(v->GetClassName(), expectedClassName) != 0) { failed = 1; - cout << "Test Failed" << endl; + cout << "Test Failed:\nExpected classname: " << expectedClassName + << "\nCreated classname: " << v->GetClassName() << endl; } } diff --git a/Common/Core/vtkDebugLeaks.h b/Common/Core/vtkDebugLeaks.h index e4c0de6788f..1c7b5a98310 100644 --- a/Common/Core/vtkDebugLeaks.h +++ b/Common/Core/vtkDebugLeaks.h @@ -13,18 +13,38 @@ =========================================================================*/ /** - * @class vtkDebugLeaks - * @brief identify memory leaks at program termination + * @class vtkDebugLeaks + * @brief identify memory leaks at program termination + * vtkDebugLeaks is used to report memory leaks at the exit of the program. It + * uses vtkObjectBase::InitializeObjectBase() (called via vtkObjectFactory + * macros) to intercept the construction of all VTK objects. It uses the + * UnRegisterInternal method of vtkObjectBase to intercept the destruction of + * all objects. * - * vtkDebugLeaks is used to report memory leaks at the exit of the program. - * It uses the vtkObjectFactory to intercept the construction of all VTK - * objects. It uses the UnRegister method of vtkObject to intercept the - * destruction of all objects. A table of object name to number of instances - * is kept. At the exit of the program if there are still VTK objects around - * it will print them out. To enable this class add the flag - * -DVTK_DEBUG_LEAKS to the compile line, and rebuild vtkObject and - * vtkObjectFactory. -*/ + * If not using the vtkObjectFactory macros to implement New(), be sure to call + * vtkObjectBase::InitializeObjectBase() explicitly on the constructed + * instance. The rule of thumb is that wherever "new [some vtkObjectBase + * subclass]" is called, vtkObjectBase::InitializeObjectBase() must be called + * as well. + * + * There are exceptions to this: + * + * - vtkCommand subclasses traditionally do not fully participate in + * vtkDebugLeaks registration, likely because they typically do not use + * vtkTypeMacro to configure GetClassName. InitializeObjectBase should not be + * called on vtkCommand subclasses, and all such classes will be automatically + * registered with vtkDebugLeaks as "vtkCommand or subclass". + * + * - vtkInformationKey subclasses are not reference counted. They are allocated + * statically and registered automatically with a singleton "manager" instance. + * The manager ensures that all keys are cleaned up before exiting, and + * registration/deregistration with vtkDebugLeaks is bypassed. + * + * A table of object name to number of instances is kept. At the exit of the + * program if there are still VTK objects around it will print them out. To + * enable this class add the flag -DVTK_DEBUG_LEAKS to the compile line, and + * rebuild vtkObject and vtkObjectFactory. + */ #ifndef vtkDebugLeaks_h #define vtkDebugLeaks_h diff --git a/Common/Core/vtkDenseArray.txx b/Common/Core/vtkDenseArray.txx index 0948ae8d798..7c315c9e929 100644 --- a/Common/Core/vtkDenseArray.txx +++ b/Common/Core/vtkDenseArray.txx @@ -22,6 +22,8 @@ #ifndef vtkDenseArray_txx #define vtkDenseArray_txx +#include "vtkObjectFactory.h" + /////////////////////////////////////////////////////////////////////////////// // vtkDenseArray::MemoryBlock @@ -72,12 +74,11 @@ T* vtkDenseArray::StaticMemoryBlock::GetAddress() template vtkDenseArray* vtkDenseArray::New() { - vtkObject* ret = vtkObjectFactory::CreateInstance(typeid(ThisT).name()); - if(ret) - { - return static_cast(ret); - } - return new ThisT(); + // Don't use object factory macros on templated classes. It'll confuse the + // object factory. + vtkDenseArray *ret = new vtkDenseArray; + ret->InitializeObjectBase(); + return ret; } template diff --git a/Common/Core/vtkDynamicLoader.cxx b/Common/Core/vtkDynamicLoader.cxx index 69ae29c996e..6c8643dd894 100644 --- a/Common/Core/vtkDynamicLoader.cxx +++ b/Common/Core/vtkDynamicLoader.cxx @@ -15,15 +15,13 @@ #include "vtkDynamicLoader.h" #include "vtkDebugLeaks.h" +#include "vtkObjectFactory.h" //----------------------------------------------------------------------------- vtkDynamicLoader* vtkDynamicLoader::New() { -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::ConstructClass("vtkDynamicLoader"); -#endif - return new vtkDynamicLoader; + VTK_STANDARD_NEW_BODY(vtkDynamicLoader) } diff --git a/Common/Core/vtkIndent.cxx b/Common/Core/vtkIndent.cxx index 17fd1cd0e3f..ab1a4f22fe4 100644 --- a/Common/Core/vtkIndent.cxx +++ b/Common/Core/vtkIndent.cxx @@ -18,14 +18,7 @@ //------------------------------------------------------------------------------ vtkIndent* vtkIndent::New() { - // First try to create the object from the vtkObjectFactory - vtkObject* ret = vtkObjectFactory::CreateInstance("vtkIndent"); - if(ret) - { - return reinterpret_cast(ret); - } - // If the factory was unable to create the object, then create it here. - return new vtkIndent; + return new vtkIndent; // not a VTK object, don't use object factory macros } diff --git a/Common/Core/vtkInformationDoubleKey.cxx b/Common/Core/vtkInformationDoubleKey.cxx index 019b2153d84..db54c0b5c69 100644 --- a/Common/Core/vtkInformationDoubleKey.cxx +++ b/Common/Core/vtkInformationDoubleKey.cxx @@ -64,7 +64,7 @@ void vtkInformationDoubleKey::Set(vtkInformation* info, double value) { // Allocate a new value. vtkInformationDoubleValue* v = new vtkInformationDoubleValue; - this->ConstructClass("vtkInformationDoubleValue"); + v->InitializeObjectBase(); v->Value = value; this->SetAsObjectBase(info, v); v->Delete(); diff --git a/Common/Core/vtkInformationDoubleVectorKey.cxx b/Common/Core/vtkInformationDoubleVectorKey.cxx index 8f441fec51b..525b13ce429 100644 --- a/Common/Core/vtkInformationDoubleVectorKey.cxx +++ b/Common/Core/vtkInformationDoubleVectorKey.cxx @@ -83,7 +83,7 @@ void vtkInformationDoubleVectorKey::Set(vtkInformation* info, } vtkInformationDoubleVectorValue* v = new vtkInformationDoubleVectorValue; - this->ConstructClass("vtkInformationDoubleVectorValue"); + v->InitializeObjectBase(); v->Value.insert(v->Value.begin(), value, value+length); this->SetAsObjectBase(info, v); v->Delete(); diff --git a/Common/Core/vtkInformationIdTypeKey.cxx b/Common/Core/vtkInformationIdTypeKey.cxx index 182ab092685..7abbd807c85 100644 --- a/Common/Core/vtkInformationIdTypeKey.cxx +++ b/Common/Core/vtkInformationIdTypeKey.cxx @@ -64,7 +64,7 @@ void vtkInformationIdTypeKey::Set(vtkInformation* info, vtkIdType value) { // Allocate a new value. vtkInformationIdTypeValue* v = new vtkInformationIdTypeValue; - this->ConstructClass("vtkInformationIdTypeValue"); + v->InitializeObjectBase(); v->Value = value; this->SetAsObjectBase(info, v); v->Delete(); diff --git a/Common/Core/vtkInformationIntegerKey.cxx b/Common/Core/vtkInformationIntegerKey.cxx index abf53429c09..ca7c7ce3015 100644 --- a/Common/Core/vtkInformationIntegerKey.cxx +++ b/Common/Core/vtkInformationIntegerKey.cxx @@ -64,7 +64,7 @@ void vtkInformationIntegerKey::Set(vtkInformation* info, int value) { // Allocate a new value. vtkInformationIntegerValue* v = new vtkInformationIntegerValue; - this->ConstructClass("vtkInformationIntegerValue"); + v->InitializeObjectBase(); v->Value = value; this->SetAsObjectBase(info, v); v->Delete(); diff --git a/Common/Core/vtkInformationIntegerPointerKey.cxx b/Common/Core/vtkInformationIntegerPointerKey.cxx index 842bbbcc495..a61fb98ce3c 100644 --- a/Common/Core/vtkInformationIntegerPointerKey.cxx +++ b/Common/Core/vtkInformationIntegerPointerKey.cxx @@ -70,7 +70,7 @@ void vtkInformationIntegerPointerKey::Set(vtkInformation* info, int* value, // Allocate a new value. vtkInformationIntegerPointerValue* v = new vtkInformationIntegerPointerValue; - this->ConstructClass("vtkInformationIntegerPointerValue"); + v->InitializeObjectBase(); v->Value = value; v->Length = length; this->SetAsObjectBase(info, v); diff --git a/Common/Core/vtkInformationIntegerVectorKey.cxx b/Common/Core/vtkInformationIntegerVectorKey.cxx index dc18f83b42b..32f2d36bbdf 100644 --- a/Common/Core/vtkInformationIntegerVectorKey.cxx +++ b/Common/Core/vtkInformationIntegerVectorKey.cxx @@ -107,7 +107,7 @@ void vtkInformationIntegerVectorKey::Set(vtkInformation* info, // Allocate a new value. vtkInformationIntegerVectorValue* v = new vtkInformationIntegerVectorValue; - this->ConstructClass("vtkInformationIntegerVectorValue"); + v->InitializeObjectBase(); v->Value.insert(v->Value.begin(), value, value+length); this->SetAsObjectBase(info, v); v->Delete(); diff --git a/Common/Core/vtkInformationKey.cxx b/Common/Core/vtkInformationKey.cxx index 216ad0ae73a..39b16038831 100644 --- a/Common/Core/vtkInformationKey.cxx +++ b/Common/Core/vtkInformationKey.cxx @@ -156,13 +156,6 @@ void vtkInformationKey::ReportAsObjectBase(vtkInformation* info, } //---------------------------------------------------------------------------- -#ifdef VTK_DEBUG_LEAKS -void vtkInformationKey::ConstructClass(const char* name) -{ - vtkDebugLeaks::ConstructClass(name); -} -#else void vtkInformationKey::ConstructClass(const char*) { } -#endif diff --git a/Common/Core/vtkInformationKeyVectorKey.cxx b/Common/Core/vtkInformationKeyVectorKey.cxx index 5426089822f..50f405c338a 100644 --- a/Common/Core/vtkInformationKeyVectorKey.cxx +++ b/Common/Core/vtkInformationKeyVectorKey.cxx @@ -99,9 +99,8 @@ void vtkInformationKeyVectorKey::Set(vtkInformation* info, { if(value) { - vtkInformationKeyVectorValue* v = - new vtkInformationKeyVectorValue; - this->ConstructClass("vtkInformationKeyVectorValue"); + vtkInformationKeyVectorValue* v = new vtkInformationKeyVectorValue; + v->InitializeObjectBase(); v->Value.insert(v->Value.begin(), value, value+length); this->SetAsObjectBase(info, v); v->Delete(); diff --git a/Common/Core/vtkInformationObjectBaseVectorKey.cxx b/Common/Core/vtkInformationObjectBaseVectorKey.cxx index 33170723e1a..c2e7d167fa5 100644 --- a/Common/Core/vtkInformationObjectBaseVectorKey.cxx +++ b/Common/Core/vtkInformationObjectBaseVectorKey.cxx @@ -75,7 +75,7 @@ vtkInformationObjectBaseVectorValue * if(base==NULL) { base=new vtkInformationObjectBaseVectorValue; - this->ConstructClass("vtkInformationObjectBaseVectorValue"); // For debug info + base->InitializeObjectBase(); this->SetAsObjectBase(info, base); base->Delete(); } diff --git a/Common/Core/vtkInformationStringKey.cxx b/Common/Core/vtkInformationStringKey.cxx index 2d58cef982b..3d83d6c6b04 100644 --- a/Common/Core/vtkInformationStringKey.cxx +++ b/Common/Core/vtkInformationStringKey.cxx @@ -68,7 +68,7 @@ void vtkInformationStringKey::Set(vtkInformation* info, const char* value) { // Allocate a new value. vtkInformationStringValue* v = new vtkInformationStringValue; - this->ConstructClass("vtkInformationStringValue"); + v->InitializeObjectBase(); v->Value = value; this->SetAsObjectBase(info, v); v->Delete(); diff --git a/Common/Core/vtkInformationStringVectorKey.cxx b/Common/Core/vtkInformationStringVectorKey.cxx index 36ad8dc91f9..c5e01c2c236 100644 --- a/Common/Core/vtkInformationStringVectorKey.cxx +++ b/Common/Core/vtkInformationStringVectorKey.cxx @@ -92,7 +92,7 @@ void vtkInformationStringVectorKey::Set(vtkInformation* info, const char* value, { vtkInformationStringVectorValue* v = new vtkInformationStringVectorValue; - this->ConstructClass("vtkInformationStringVectorValue"); + v->InitializeObjectBase(); while(static_cast(v->Value.size()) <= index) { v->Value.push_back(""); diff --git a/Common/Core/vtkInformationUnsignedLongKey.cxx b/Common/Core/vtkInformationUnsignedLongKey.cxx index e07da669ddf..f5250e5773d 100644 --- a/Common/Core/vtkInformationUnsignedLongKey.cxx +++ b/Common/Core/vtkInformationUnsignedLongKey.cxx @@ -65,7 +65,7 @@ void vtkInformationUnsignedLongKey::Set(vtkInformation* info, { // Allocate a new value. vtkInformationUnsignedLongValue* v = new vtkInformationUnsignedLongValue; - this->ConstructClass("vtkInformationUnsignedLongValue"); + v->InitializeObjectBase(); v->Value = value; this->SetAsObjectBase(info, v); v->Delete(); diff --git a/Common/Core/vtkInformationVariantKey.cxx b/Common/Core/vtkInformationVariantKey.cxx index a0fe3951a02..6c3cdb1f56f 100644 --- a/Common/Core/vtkInformationVariantKey.cxx +++ b/Common/Core/vtkInformationVariantKey.cxx @@ -68,7 +68,7 @@ void vtkInformationVariantKey::Set(vtkInformation* info, const vtkVariant& value { // Allocate a new value. vtkInformationVariantValue* v = new vtkInformationVariantValue; - this->ConstructClass("vtkInformationVariantValue"); + v->InitializeObjectBase(); v->Value = value; this->SetAsObjectBase(info, v); v->Delete(); diff --git a/Common/Core/vtkInformationVariantVectorKey.cxx b/Common/Core/vtkInformationVariantVectorKey.cxx index 98a5781d1d1..62c90c36634 100644 --- a/Common/Core/vtkInformationVariantVectorKey.cxx +++ b/Common/Core/vtkInformationVariantVectorKey.cxx @@ -86,7 +86,7 @@ void vtkInformationVariantVectorKey::Set(vtkInformation* info, const vtkVariant* } vtkInformationVariantVectorValue* v = new vtkInformationVariantVectorValue; - this->ConstructClass("vtkInformationVariantVectorValue"); + v->InitializeObjectBase(); v->Value.insert(v->Value.begin(), value, value+length); this->SetAsObjectBase(info, v); v->Delete(); diff --git a/Common/Core/vtkMath.cxx b/Common/Core/vtkMath.cxx index 3f1cf678e64..46096eb014f 100644 --- a/Common/Core/vtkMath.cxx +++ b/Common/Core/vtkMath.cxx @@ -45,10 +45,10 @@ class vtkMathInternal : public vtkObjectBase vtkBaseTypeMacro(vtkMathInternal, vtkObjectBase); static vtkMathInternal* New() { -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::ConstructClass("vtkMathInternal"); -#endif - return new vtkMathInternal(); + // Can't use object factory macros, since they cast to vtkObject*. + vtkMathInternal *ret = new vtkMathInternal; + ret->InitializeObjectBase(); + return ret; } vtkMinimalStandardRandomSequence *Uniform; diff --git a/Common/Core/vtkObject.cxx b/Common/Core/vtkObject.cxx index 181ab4e4150..742d9b80418 100644 --- a/Common/Core/vtkObject.cxx +++ b/Common/Core/vtkObject.cxx @@ -17,6 +17,7 @@ #include "vtkCommand.h" #include "vtkDebugLeaks.h" #include "vtkGarbageCollector.h" +#include "vtkObjectFactory.h" #include "vtkTimeStamp.h" #include "vtkWeakPointer.h" @@ -126,10 +127,9 @@ class vtkSubjectHelper vtkObject *vtkObject::New() { -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::ConstructClass("vtkObject"); -#endif - return new vtkObject; + vtkObject *ret = new vtkObject; + ret->InitializeObjectBase(); + return ret; } diff --git a/Common/Core/vtkObjectBase.cxx b/Common/Core/vtkObjectBase.cxx index a9aa4576b2a..ca6d6e7f039 100644 --- a/Common/Core/vtkObjectBase.cxx +++ b/Common/Core/vtkObjectBase.cxx @@ -94,6 +94,14 @@ vtkObjectBase::~vtkObjectBase() } } +//---------------------------------------------------------------------------- +void vtkObjectBase::InitializeObjectBase() +{ +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::ConstructClass(this->GetClassName()); +#endif // VTK_DEBUG_LEAKS +} + //---------------------------------------------------------------------------- #ifdef VTK_WORKAROUND_WINDOWS_MANGLE # undef GetClassName diff --git a/Common/Core/vtkObjectBase.h b/Common/Core/vtkObjectBase.h index 6ca96546026..ccb61dee1fc 100644 --- a/Common/Core/vtkObjectBase.h +++ b/Common/Core/vtkObjectBase.h @@ -43,6 +43,11 @@ #ifndef vtkObjectBase_h #define vtkObjectBase_h +// Semantics around vtkDebugLeaks usage has changed. Now just call +// vtkObjectBase::InitializeObjectBase() after creating an object with New(). +// The object factory methods take care of this automatically. +#define VTK_HAS_INITIALIZE_OBJECT_BASE + #include "vtkCommonCoreModule.h" // For export macro #include "vtkIndent.h" #include "vtkSystemIncludes.h" @@ -120,7 +125,15 @@ class VTKCOMMONCORE_EXPORT vtkObjectBase * to zero, and reference counting on. */ static vtkObjectBase *New() - {return new vtkObjectBase;} + { + vtkObjectBase *o = new vtkObjectBase; + o->InitializeObjectBase(); + return o; + } + + // Called by implementations of vtkObject::New(). Centralized location for + // vtkDebugLeaks registration: + void InitializeObjectBase(); #ifdef _WIN32 // avoid dll boundary problems diff --git a/Common/Core/vtkObjectFactory.cxx b/Common/Core/vtkObjectFactory.cxx index 9b6fcb18409..032f7476717 100644 --- a/Common/Core/vtkObjectFactory.cxx +++ b/Common/Core/vtkObjectFactory.cxx @@ -47,7 +47,7 @@ static vtkCleanUpObjectFactory vtkCleanUpObjectFactoryGlobal; // factories vtkObject* vtkObjectFactory::CreateInstance(const char* vtkclassname, - bool isAbstract) + bool) { if(!vtkObjectFactory::RegisteredFactories) { @@ -66,29 +66,15 @@ vtkObject* vtkObjectFactory::CreateInstance(const char* vtkclassname, return newobject; } } - // if the factory does not create the object, then - // the object will be created with the name passed in, - // so register the construction - if (!isAbstract) - { -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::ConstructClass(vtkclassname); -#endif - } return 0; } -#ifdef VTK_DEBUG_LEAKS -void vtkObjectFactory::ConstructInstance(const char* vtkclassname) -{ - vtkDebugLeaks::ConstructClass(vtkclassname); -} -#else void vtkObjectFactory::ConstructInstance(const char*) { + // no-op. Call vtkObjectBase::InitializeObjectBase() from the New() + // implementation instead. } -#endif // A one time initialization method. void vtkObjectFactory::Init() diff --git a/Common/Core/vtkObjectFactory.h b/Common/Core/vtkObjectFactory.h index dccf56f9820..edf07487450 100644 --- a/Common/Core/vtkObjectFactory.h +++ b/Common/Core/vtkObjectFactory.h @@ -55,17 +55,17 @@ class VTKCOMMONCORE_EXPORT vtkObjectFactory : public vtkObject * Each loaded vtkObjectFactory will be asked in the order * the factory was in the VTK_AUTOLOAD_PATH. After the * first factory returns the object no other factories are asked. - * If the requested class is abstract, set isAbstract to true. Otherwise - * it is assumed that an instance of 'vtkclassname' will be instantiated - * by the caller when no override is found. + * isAbstract is no longer used. This method calls + * vtkObjectBase::InitializeObjectBase() on the instance when the + * return value is non-NULL. */ VTK_NEWINSTANCE static vtkObject* CreateInstance(const char* vtkclassname, bool isAbstract = false); /** - * Call vtkDebugLeaks::ConstructClass if necessary. Does not attempt - * to use the object factory to create an instance. + * No longer used. Call vtkObjectBase::InitializeObjectBase() from the + * New() implementation instead. */ static void ConstructInstance(const char* vtkclassname); @@ -327,7 +327,9 @@ vtkObjectFactory* vtkLoad() \ { \ return static_cast(ret); \ } \ - return new thisClass; + thisClass *result = new thisClass; \ + result->InitializeObjectBase(); \ + return result; // Macro to implement the body of the abstract object factory form of the New() // method, i.e. an abstract base class that can only be instantiated if the @@ -345,14 +347,11 @@ vtkObjectFactory* vtkLoad() \ #if defined(VTK_ALL_NEW_OBJECT_FACTORY) # define VTK_STANDARD_NEW_BODY(thisClass) \ VTK_OBJECT_FACTORY_NEW_BODY(thisClass) -#elif defined(VTK_DEBUG_LEAKS) +#else # define VTK_STANDARD_NEW_BODY(thisClass) \ thisClass *result = new thisClass; \ - vtkObjectFactory::ConstructInstance(result->GetClassName()); \ + result->InitializeObjectBase(); \ return result; -#else -# define VTK_STANDARD_NEW_BODY(thisClass) \ - return new thisClass; #endif // Macro to implement the standard form of the New() method. diff --git a/Common/Core/vtkObjectFactoryCollection.cxx b/Common/Core/vtkObjectFactoryCollection.cxx index c1e8b0b1eb4..06b51e001af 100644 --- a/Common/Core/vtkObjectFactoryCollection.cxx +++ b/Common/Core/vtkObjectFactoryCollection.cxx @@ -15,13 +15,13 @@ #include "vtkObjectFactoryCollection.h" #include "vtkDebugLeaks.h" - +#include "vtkObjectFactory.h" vtkObjectFactoryCollection* vtkObjectFactoryCollection::New() { -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::ConstructClass("vtkObjectFactoryCollection"); -#endif - return new vtkObjectFactoryCollection; + // Don't use the object factory macros. Creating an object factory here + // will cause an infinite loop. + vtkObjectFactoryCollection *ret = new vtkObjectFactoryCollection; + ret->InitializeObjectBase(); + return ret; } - diff --git a/Common/Core/vtkOutputWindow.cxx b/Common/Core/vtkOutputWindow.cxx index 2c98f1aa152..b2e970b10b0 100644 --- a/Common/Core/vtkOutputWindow.cxx +++ b/Common/Core/vtkOutputWindow.cxx @@ -149,22 +149,14 @@ vtkOutputWindow* vtkOutputWindow::GetInstance() // if the factory did not provide one, then create it here if(!vtkOutputWindow::Instance) { - // if the factory failed to create the object, - // then destroy it now, as vtkDebugLeaks::ConstructClass was called - // with "vtkOutputWindow", and not the real name of the class #if defined( _WIN32 ) && !defined( VTK_USE_X ) -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::DestructClass("vtkOutputWindow"); -#endif vtkOutputWindow::Instance = vtkWin32OutputWindow::New(); #else #if defined( ANDROID ) -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::DestructClass("vtkOutputWindow"); -#endif vtkOutputWindow::Instance = vtkAndroidOutputWindow::New(); #else vtkOutputWindow::Instance = new vtkOutputWindow; + vtkOutputWindow::Instance->InitializeObjectBase(); #endif #endif } diff --git a/Common/Core/vtkPoints.cxx b/Common/Core/vtkPoints.cxx index 3e7c24b21e1..8444899d1c9 100644 --- a/Common/Core/vtkPoints.cxx +++ b/Common/Core/vtkPoints.cxx @@ -44,7 +44,9 @@ vtkPoints* vtkPoints::New(int dataType) return static_cast(ret); } // If the factory was unable to create the object, then create it here. - return new vtkPoints(dataType); + vtkPoints *result = new vtkPoints(dataType); + result->InitializeObjectBase(); + return result; } vtkPoints* vtkPoints::New() diff --git a/Common/Core/vtkPoints2D.cxx b/Common/Core/vtkPoints2D.cxx index 9fcc6e2156e..a14b81df0e2 100644 --- a/Common/Core/vtkPoints2D.cxx +++ b/Common/Core/vtkPoints2D.cxx @@ -44,7 +44,9 @@ vtkPoints2D* vtkPoints2D::New(int dataType) return static_cast(ret); } // If the factory was unable to create the object, then create it here. - return new vtkPoints2D(dataType); + vtkPoints2D *result = new vtkPoints2D(dataType); + result->InitializeObjectBase(); + return result; } vtkPoints2D* vtkPoints2D::New() diff --git a/Common/Core/vtkSparseArray.txx b/Common/Core/vtkSparseArray.txx index 53b28a23b49..c8f99e07169 100644 --- a/Common/Core/vtkSparseArray.txx +++ b/Common/Core/vtkSparseArray.txx @@ -28,12 +28,11 @@ template vtkSparseArray* vtkSparseArray::New() { - vtkObject* ret = vtkObjectFactory::CreateInstance(typeid(ThisT).name()); - if(ret) - { - return static_cast(ret); - } - return new ThisT(); + // Don't use object factory macros on templates, it'll confuse the object + // factory. + vtkSparseArray *ret = new vtkSparseArray; + ret->InitializeObjectBase(); + return ret; } template diff --git a/Common/DataModel/vtkHyperOctree.cxx b/Common/DataModel/vtkHyperOctree.cxx index a272e7b54f3..4bd38797a66 100644 --- a/Common/DataModel/vtkHyperOctree.cxx +++ b/Common/DataModel/vtkHyperOctree.cxx @@ -129,17 +129,11 @@ template class vtkCompactHyperOctreeCursor //--------------------------------------------------------------------------- static vtkCompactHyperOctreeCursor *New() { - vtkObject *ret= - vtkObjectFactory::CreateInstance("vtkCompactHyperOctreeCursor"); - - if(ret!=0) - { - return static_cast *>(ret); - } - else - { - return new vtkCompactHyperOctreeCursor; - } + // Don't use object factory macros with templates. It'll confuse the + // object factory. + vtkCompactHyperOctreeCursor *ret = new vtkCompactHyperOctreeCursor; + ret->InitializeObjectBase(); + return ret; } vtkTypeMacro(vtkCompactHyperOctreeCursor,vtkHyperOctreeCursor); @@ -655,17 +649,9 @@ template class vtkCompactHyperOctree //--------------------------------------------------------------------------- static vtkCompactHyperOctree *New() { - vtkObject *ret= - vtkObjectFactory::CreateInstance("vtkCompactHyperOctree"); - - if(ret!=0) - { - return static_cast *>(ret); - } - else - { - return new vtkCompactHyperOctree; - } + vtkCompactHyperOctree *result = new vtkCompactHyperOctree; + result->InitializeObjectBase(); + return result; } vtkTypeMacro(vtkCompactHyperOctree,vtkHyperOctreeInternal); diff --git a/Common/DataModel/vtkHyperTree.cxx b/Common/DataModel/vtkHyperTree.cxx index d0a284b67b9..747b94d1653 100644 --- a/Common/DataModel/vtkHyperTree.cxx +++ b/Common/DataModel/vtkHyperTree.cxx @@ -37,10 +37,9 @@ template class vtkCompactHyperTreeCursor : public vtkHyperTreeCursor static vtkCompactHyperTreeCursor* New() { - vtkObject* o = - vtkObjectFactory::CreateInstance( "vtkCompactHyperTreeCursor" ); - return o ? static_cast *>( o ) : - new vtkCompactHyperTreeCursor(); + vtkCompactHyperTreeCursor *ret = new vtkCompactHyperTreeCursor; + ret->InitializeObjectBase(); + return ret; } //--------------------------------------------------------------------------- @@ -595,9 +594,9 @@ template class vtkCompactHyperTree : public vtkHyperTree //--------------------------------------------------------------------------- static vtkCompactHyperTree* New() { - vtkObject* o = vtkObjectFactory::CreateInstance( "vtkCompactHyperTree" ); - return o ? - static_cast *>(o) : new vtkCompactHyperTree; + vtkCompactHyperTree *ret = new vtkCompactHyperTree; + ret->InitializeObjectBase(); + return ret; } //--------------------------------------------------------------------------- diff --git a/Common/DataModel/vtkInformationQuadratureSchemeDefinitionVectorKey.cxx b/Common/DataModel/vtkInformationQuadratureSchemeDefinitionVectorKey.cxx index 4029b109e5b..485fb7cf431 100644 --- a/Common/DataModel/vtkInformationQuadratureSchemeDefinitionVectorKey.cxx +++ b/Common/DataModel/vtkInformationQuadratureSchemeDefinitionVectorKey.cxx @@ -72,7 +72,7 @@ vtkInformationQuadratureSchemeDefinitionVectorValue * if(base == NULL) { base=new vtkInformationQuadratureSchemeDefinitionVectorValue; - this->ConstructClass("vtkInformationQuadratureSchemeDefinitionVectorValue"); // For debug info + base->InitializeObjectBase(); this->SetAsObjectBase(info, base); base->Delete(); } diff --git a/Common/ExecutionModel/Testing/Cxx/TestThreadedImageAlgorithmSplitExtent.cxx b/Common/ExecutionModel/Testing/Cxx/TestThreadedImageAlgorithmSplitExtent.cxx index c6e324de694..0c352b86047 100644 --- a/Common/ExecutionModel/Testing/Cxx/TestThreadedImageAlgorithmSplitExtent.cxx +++ b/Common/ExecutionModel/Testing/Cxx/TestThreadedImageAlgorithmSplitExtent.cxx @@ -16,6 +16,7 @@ // This test checks the SplitExtent method of vtkThreadedImageAlgorithm. #include "vtkNew.h" +#include "vtkObjectFactory.h" #include "vtkThreadedImageAlgorithm.h" #define TEST_SUCCESS 0 @@ -32,10 +33,7 @@ class ThreadedImageAlgorithmTester : bool TestSplitExtent(int extent[6], vtkIdType pieces); }; -ThreadedImageAlgorithmTester *ThreadedImageAlgorithmTester::New() -{ - return new ThreadedImageAlgorithmTester; -} +vtkStandardNewMacro(ThreadedImageAlgorithmTester) // The SplitPath is protected, so add a method to set it. void ThreadedImageAlgorithmTester::SetSplitPath(const int path[3], int len) diff --git a/Common/ExecutionModel/vtkInformationExecutivePortKey.cxx b/Common/ExecutionModel/vtkInformationExecutivePortKey.cxx index 3f3fa16985d..7885e5f9d53 100644 --- a/Common/ExecutionModel/vtkInformationExecutivePortKey.cxx +++ b/Common/ExecutionModel/vtkInformationExecutivePortKey.cxx @@ -69,7 +69,7 @@ void vtkInformationExecutivePortKey::Set(vtkInformation* info, // Allocate a new value. vtkInformationExecutivePortValue* v = new vtkInformationExecutivePortValue; - this->ConstructClass("vtkInformationExecutivePortValue"); + v->InitializeObjectBase(); v->Executive = executive; v->Port = port; this->SetAsObjectBase(info, v); diff --git a/Common/ExecutionModel/vtkInformationExecutivePortVectorKey.cxx b/Common/ExecutionModel/vtkInformationExecutivePortVectorKey.cxx index 23fd0985f1e..1e116eaf9f2 100644 --- a/Common/ExecutionModel/vtkInformationExecutivePortVectorKey.cxx +++ b/Common/ExecutionModel/vtkInformationExecutivePortVectorKey.cxx @@ -171,7 +171,7 @@ void vtkInformationExecutivePortVectorKey::Set(vtkInformation* info, // Allocate a new value. vtkInformationExecutivePortVectorValue* v = new vtkInformationExecutivePortVectorValue; - this->ConstructClass("vtkInformationExecutivePortVectorValue"); + v->InitializeObjectBase(); v->Executives.insert(v->Executives.begin(), executives, executives+length); v->Ports.insert(v->Ports.begin(), ports, ports+length); this->SetAsObjectBase(info, v); diff --git a/Common/ExecutionModel/vtkThreadedCompositeDataPipeline.cxx b/Common/ExecutionModel/vtkThreadedCompositeDataPipeline.cxx index 667435c3e96..ad54cf55cb2 100644 --- a/Common/ExecutionModel/vtkThreadedCompositeDataPipeline.cxx +++ b/Common/ExecutionModel/vtkThreadedCompositeDataPipeline.cxx @@ -82,12 +82,10 @@ class ProcessBlockData: public vtkObjectBase static ProcessBlockData* New() { - // This is required everytime we're implementing our own New() to avoid - // "Deleting unknown object" warning from vtkDebugLeaks. -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::ConstructClass("ProcessBlockData"); -#endif - return new ProcessBlockData(); + // Can't use object factory macros, this is not a vtkObject. + ProcessBlockData *ret = new ProcessBlockData; + ret->InitializeObjectBase(); + return ret; } void Construct(vtkInformationVector** inInfoVec, diff --git a/Common/System/vtkDirectory.cxx b/Common/System/vtkDirectory.cxx index 37c427fd9c9..937c1c5fb08 100644 --- a/Common/System/vtkDirectory.cxx +++ b/Common/System/vtkDirectory.cxx @@ -16,19 +16,12 @@ #include "vtkStringArray.h" #include "vtkDebugLeaks.h" +#include "vtkObjectFactory.h" #include #include - -//---------------------------------------------------------------------------- -vtkDirectory* vtkDirectory::New() -{ -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::ConstructClass("vtkDirectory"); -#endif - return new vtkDirectory; -} +vtkStandardNewMacro(vtkDirectory) vtkDirectory::vtkDirectory() : Path(0) diff --git a/Common/Transforms/vtkAbstractTransform.cxx b/Common/Transforms/vtkAbstractTransform.cxx index 904e87e9940..fcf86cbbdd5 100644 --- a/Common/Transforms/vtkAbstractTransform.cxx +++ b/Common/Transforms/vtkAbstractTransform.cxx @@ -18,6 +18,7 @@ #include "vtkDataArray.h" #include "vtkDebugLeaks.h" #include "vtkHomogeneousTransform.h" +#include "vtkObjectFactory.h" #include "vtkMath.h" #include "vtkMatrix4x4.h" #include "vtkPoints.h" @@ -360,11 +361,7 @@ class vtkSimpleTransform : public vtkHomogeneousTransform { public: vtkTypeMacro(vtkSimpleTransform,vtkHomogeneousTransform); - static vtkSimpleTransform *New() { -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::ConstructClass("vtkSimpleTransform"); -#endif - return new vtkSimpleTransform; }; + static vtkSimpleTransform *New() { VTK_STANDARD_NEW_BODY(vtkSimpleTransform) } vtkAbstractTransform *MakeTransform() VTK_OVERRIDE { return vtkSimpleTransform::New(); }; void Inverse() VTK_OVERRIDE { this->Matrix->Invert(); this->Modified(); }; protected: diff --git a/IO/Core/vtkGlobFileNames.cxx b/IO/Core/vtkGlobFileNames.cxx index 0695521ebb1..c1b00e077f2 100644 --- a/IO/Core/vtkGlobFileNames.cxx +++ b/IO/Core/vtkGlobFileNames.cxx @@ -16,6 +16,7 @@ #include "vtkStringArray.h" #include "vtkDebugLeaks.h" +#include "vtkObjectFactory.h" #include #include @@ -27,10 +28,7 @@ //---------------------------------------------------------------------------- vtkGlobFileNames* vtkGlobFileNames::New() { -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::ConstructClass("vtkGlobFileNames"); -#endif - return new vtkGlobFileNames; + VTK_STANDARD_NEW_BODY(vtkGlobFileNames) } //---------------------------------------------------------------------------- diff --git a/IO/Infovis/vtkPhyloXMLTreeReader.cxx b/IO/Infovis/vtkPhyloXMLTreeReader.cxx index 3c869cda8f7..6ce140b2c15 100644 --- a/IO/Infovis/vtkPhyloXMLTreeReader.cxx +++ b/IO/Infovis/vtkPhyloXMLTreeReader.cxx @@ -557,12 +557,12 @@ void vtkPhyloXMLTreeReader::ReadPropertyElement(vtkXMLDataElement *element, { // authority (required attribute) vtkInformationStringKey *authorityKey = - new vtkInformationStringKey("authority", "vtkPhyloXMLTreeReader"); + vtkInformationStringKey::MakeKey("authority", "vtkPhyloXMLTreeReader"); propertyArray->GetInformation()->Set(authorityKey, authority.c_str()); // applies_to (required attribute) vtkInformationStringKey *appliesToKey = - new vtkInformationStringKey("applies_to", "vtkPhyloXMLTreeReader"); + vtkInformationStringKey::MakeKey("applies_to", "vtkPhyloXMLTreeReader"); propertyArray->GetInformation()->Set(appliesToKey, appliesTo); // unit (optional attribute) @@ -570,7 +570,7 @@ void vtkPhyloXMLTreeReader::ReadPropertyElement(vtkXMLDataElement *element, if (unit) { vtkInformationStringKey *unitKey = - new vtkInformationStringKey("unit", "vtkPhyloXMLTreeReader"); + vtkInformationStringKey::MakeKey("unit", "vtkPhyloXMLTreeReader"); propertyArray->GetInformation()->Set(unitKey, unit); } } @@ -617,7 +617,7 @@ void vtkPhyloXMLTreeReader::ReadConfidenceElement(vtkXMLDataElement *element, // add the confidence type as an Information type on this array vtkInformationStringKey *key = - new vtkInformationStringKey("type", "vtkPhyloXMLTreeReader"); + vtkInformationStringKey::MakeKey("type", "vtkPhyloXMLTreeReader"); treeConfidence->GetInformation()->Set(key, type); g->GetVertexData()->AddArray(treeConfidence.GetPointer()); @@ -633,7 +633,7 @@ void vtkPhyloXMLTreeReader::ReadConfidenceElement(vtkXMLDataElement *element, // add the confidence type as an Information type on this array vtkInformationStringKey *key = - new vtkInformationStringKey("type", "vtkPhyloXMLTreeReader"); + vtkInformationStringKey::MakeKey("type", "vtkPhyloXMLTreeReader"); confidenceArray->GetInformation()->Set(key, type); g->GetVertexData()->AddArray(confidenceArray.GetPointer()); diff --git a/IO/Legacy/Testing/Cxx/TestLegacyArrayMetaData.cxx b/IO/Legacy/Testing/Cxx/TestLegacyArrayMetaData.cxx index 5e19e2f9fa1..e2015fb22f3 100644 --- a/IO/Legacy/Testing/Cxx/TestLegacyArrayMetaData.cxx +++ b/IO/Legacy/Testing/Cxx/TestLegacyArrayMetaData.cxx @@ -39,23 +39,23 @@ namespace { static vtkInformationDoubleKey *TestDoubleKey = - new vtkInformationDoubleKey("Double", "TestKey"); + vtkInformationDoubleKey::MakeKey("Double", "TestKey"); // Test restricted keys with this one -- must be a vector of length 3, can NOT // be constructed using Append(): static vtkInformationDoubleVectorKey *TestDoubleVectorKey = - new vtkInformationDoubleVectorKey("DoubleVector", "TestKey", 3); + vtkInformationDoubleVectorKey::MakeKey("DoubleVector", "TestKey", 3); static vtkInformationIdTypeKey *TestIdTypeKey = - new vtkInformationIdTypeKey("IdType", "TestKey"); + vtkInformationIdTypeKey::MakeKey("IdType", "TestKey"); static vtkInformationIntegerKey *TestIntegerKey = - new vtkInformationIntegerKey("Integer", "TestKey"); + vtkInformationIntegerKey::MakeKey("Integer", "TestKey"); static vtkInformationIntegerVectorKey *TestIntegerVectorKey = - new vtkInformationIntegerVectorKey("IntegerVector", "TestKey"); + vtkInformationIntegerVectorKey::MakeKey("IntegerVector", "TestKey"); static vtkInformationStringKey *TestStringKey = - new vtkInformationStringKey("String", "TestKey"); + vtkInformationStringKey::MakeKey("String", "TestKey"); static vtkInformationStringVectorKey *TestStringVectorKey = - new vtkInformationStringVectorKey("StringVector", "TestKey"); + vtkInformationStringVectorKey::MakeKey("StringVector", "TestKey"); static vtkInformationUnsignedLongKey *TestUnsignedLongKey = - new vtkInformationUnsignedLongKey("UnsignedLong", "TestKey"); + vtkInformationUnsignedLongKey::MakeKey("UnsignedLong", "TestKey"); bool stringEqual(const std::string &expect, const std::string &actual) { diff --git a/IO/XML/Testing/Cxx/TestDataObjectXMLIO.cxx b/IO/XML/Testing/Cxx/TestDataObjectXMLIO.cxx index b97abe8bcf3..9b129f53227 100644 --- a/IO/XML/Testing/Cxx/TestDataObjectXMLIO.cxx +++ b/IO/XML/Testing/Cxx/TestDataObjectXMLIO.cxx @@ -44,22 +44,22 @@ namespace { static vtkInformationDoubleKey *TestDoubleKey = - new vtkInformationDoubleKey("Double", "XMLTestKey"); + vtkInformationDoubleKey::MakeKey("Double", "XMLTestKey"); // Test RequiredLength keys. DoubleVector must have Length() == 3 static vtkInformationDoubleVectorKey *TestDoubleVectorKey = - new vtkInformationDoubleVectorKey("DoubleVector", "XMLTestKey", 3); + vtkInformationDoubleVectorKey::MakeKey("DoubleVector", "XMLTestKey", 3); static vtkInformationIdTypeKey *TestIdTypeKey = - new vtkInformationIdTypeKey("IdType", "XMLTestKey"); + vtkInformationIdTypeKey::MakeKey("IdType", "XMLTestKey"); static vtkInformationIntegerKey *TestIntegerKey = - new vtkInformationIntegerKey("Integer", "XMLTestKey"); + vtkInformationIntegerKey::MakeKey("Integer", "XMLTestKey"); static vtkInformationIntegerVectorKey *TestIntegerVectorKey = - new vtkInformationIntegerVectorKey("IntegerVector", "XMLTestKey"); + vtkInformationIntegerVectorKey::MakeKey("IntegerVector", "XMLTestKey"); static vtkInformationStringKey *TestStringKey = - new vtkInformationStringKey("String", "XMLTestKey"); + vtkInformationStringKey::MakeKey("String", "XMLTestKey"); static vtkInformationStringVectorKey *TestStringVectorKey = - new vtkInformationStringVectorKey("StringVector", "XMLTestKey"); + vtkInformationStringVectorKey::MakeKey("StringVector", "XMLTestKey"); static vtkInformationUnsignedLongKey *TestUnsignedLongKey = - new vtkInformationUnsignedLongKey("UnsignedLong", "XMLTestKey"); + vtkInformationUnsignedLongKey::MakeKey("UnsignedLong", "XMLTestKey"); bool stringEqual(const std::string &expect, const std::string &actual) { diff --git a/Parallel/MPI/vtkMPIController.cxx b/Parallel/MPI/vtkMPIController.cxx index 78ff7f0d7e6..b96fa454450 100644 --- a/Parallel/MPI/vtkMPIController.cxx +++ b/Parallel/MPI/vtkMPIController.cxx @@ -66,6 +66,7 @@ class vtkMPIOutputWindow : public vtkOutputWindow void vtkMPIController::CreateOutputWindow() { vtkMPIOutputWindow* window = new vtkMPIOutputWindow; + window->InitializeObjectBase(); window->Controller = this; this->OutputWindow = window; vtkOutputWindow::SetInstance(this->OutputWindow); diff --git a/Rendering/Core/vtkGraphicsFactory.cxx b/Rendering/Core/vtkGraphicsFactory.cxx index d167b785703..1f9f04c4e9a 100644 --- a/Rendering/Core/vtkGraphicsFactory.cxx +++ b/Rendering/Core/vtkGraphicsFactory.cxx @@ -86,12 +86,6 @@ vtkObject* vtkGraphicsFactory::CreateInstance(const char* vtkclassname ) { return ret; } - // if the factory failed to create the object, - // then destroy it now, as vtkDebugLeaks::ConstructClass was called - // with vtkclassname, and not the real name of the class -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::DestructClass(vtkclassname); -#endif return 0; } diff --git a/Rendering/Core/vtkRenderWindowInteractor.cxx b/Rendering/Core/vtkRenderWindowInteractor.cxx index 04eeec83bb8..6b11c976466 100644 --- a/Rendering/Core/vtkRenderWindowInteractor.cxx +++ b/Rendering/Core/vtkRenderWindowInteractor.cxx @@ -171,10 +171,10 @@ vtkRenderWindowInteractor *vtkRenderWindowInteractor::New() { return static_cast(ret); } -#ifdef VTK_DEBUG_LEAKS - vtkDebugLeaks::ConstructClass("vtkRenderWindowInteractor"); -#endif - return new vtkRenderWindowInteractor; + + vtkRenderWindowInteractor *o = new vtkRenderWindowInteractor; + o->InitializeObjectBase(); + return o; } //---------------------------------------------------------------------- diff --git a/Rendering/Core/vtkTextRenderer.cxx b/Rendering/Core/vtkTextRenderer.cxx index 9a0d2dd52df..1557e273cee 100644 --- a/Rendering/Core/vtkTextRenderer.cxx +++ b/Rendering/Core/vtkTextRenderer.cxx @@ -15,6 +15,7 @@ #include "vtkTextRenderer.h" +#include "vtkDebugLeaks.h" // Must be included before any singletons #include "vtkImageData.h" #include "vtkObjectFactory.h" #include "vtkPath.h" @@ -24,10 +25,6 @@ #include -#ifdef VTK_DEBUG_LEAKS -#include "vtkDebugLeaks.h" -#endif - //---------------------------------------------------------------------------- // The singleton, and the singleton cleanup vtkTextRenderer *vtkTextRenderer::Instance = NULL; @@ -76,14 +73,6 @@ vtkTextRenderer *vtkTextRenderer::GetInstance() vtkTextRenderer::Instance = static_cast( vtkObjectFactory::CreateInstance("vtkTextRenderer")); - // Clean up any leaked references from vtkDebugLeaks if needed -#ifdef VTK_DEBUG_LEAKS - if (!vtkTextRenderer::Instance) - { - vtkDebugLeaks::DestructClass("vtkTextRenderer"); - } -#endif - return vtkTextRenderer::Instance; } diff --git a/Rendering/FreeType/vtkFreeTypeTools.cxx b/Rendering/FreeType/vtkFreeTypeTools.cxx index 0443f0d5c08..16a445d9433 100644 --- a/Rendering/FreeType/vtkFreeTypeTools.cxx +++ b/Rendering/FreeType/vtkFreeTypeTools.cxx @@ -155,6 +155,7 @@ vtkFreeTypeTools* vtkFreeTypeTools::GetInstance() if (!vtkFreeTypeTools::Instance) { vtkFreeTypeTools::Instance = new vtkFreeTypeTools; + vtkFreeTypeTools::Instance->InitializeObjectBase(); } } return vtkFreeTypeTools::Instance; diff --git a/Rendering/FreeType/vtkMathTextUtilities.cxx b/Rendering/FreeType/vtkMathTextUtilities.cxx index cbf577c98a1..1eec5ff4ea6 100644 --- a/Rendering/FreeType/vtkMathTextUtilities.cxx +++ b/Rendering/FreeType/vtkMathTextUtilities.cxx @@ -15,6 +15,7 @@ #include "vtkMathTextUtilities.h" +#include "vtkDebugLeaks.h" // Must be included before any singletons #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkTextProperty.h" @@ -22,10 +23,6 @@ #include "vtkViewport.h" #include "vtkWindow.h" -#ifdef VTK_DEBUG_LEAKS -#include "vtkDebugLeaks.h" -#endif - #include //---------------------------------------------------------------------------- @@ -55,13 +52,6 @@ vtkMathTextUtilities* vtkMathTextUtilities::GetInstance() { vtkMathTextUtilities::Instance = static_cast( vtkObjectFactory::CreateInstance("vtkMathTextUtilities")); - // Clean up any leaked references from vtkDebugLeaks if needed -#ifdef VTK_DEBUG_LEAKS - if (!vtkMathTextUtilities::Instance) - { - vtkDebugLeaks::DestructClass("vtkMathTextUtilities"); - } -#endif } return vtkMathTextUtilities::Instance; From 874a7d8b3e84b5c26306055e58bd3229326a1525 Mon Sep 17 00:00:00 2001 From: "David C. Lonie" Date: Wed, 28 Sep 2016 15:56:30 -0400 Subject: [PATCH 2/3] Deprecate vtkObjectFactory::ConstructInstance(const char*) Removing this method in favor of using vtkObjectBase::InitializeObjectBase, since it uses a user-supplied string. This approach has proven fragile with templated classes. Plus, the method is only a thin wrapper around vtkDebugLeaks::ConstructClass and doesn't need to be. --- Common/Core/vtkObjectFactory.cxx | 13 +++++++++++-- Common/Core/vtkObjectFactory.h | 4 +++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Common/Core/vtkObjectFactory.cxx b/Common/Core/vtkObjectFactory.cxx index 032f7476717..28da26091b0 100644 --- a/Common/Core/vtkObjectFactory.cxx +++ b/Common/Core/vtkObjectFactory.cxx @@ -70,11 +70,20 @@ vtkObject* vtkObjectFactory::CreateInstance(const char* vtkclassname, return 0; } -void vtkObjectFactory::ConstructInstance(const char*) +#ifndef VTK_LEGACY_REMOVE +void vtkObjectFactory::ConstructInstance(const char *vtkclassname) { // no-op. Call vtkObjectBase::InitializeObjectBase() from the New() - // implementation instead. + // implementation instead. That way we ensure that the + // registration/deregistration strings match. + VTK_LEGACY_REPLACED_BODY(vtkObjectFactory::ConstructInstance, "VTK 7.1", + vtkObjectBase::InitializeObjectBase); +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::ConstructClass(vtkclassname); +#endif // VTK_DEBUG_LEAKS + } +#endif // not VTK_LEGACY_REMOVE // A one time initialization method. void vtkObjectFactory::Init() diff --git a/Common/Core/vtkObjectFactory.h b/Common/Core/vtkObjectFactory.h index edf07487450..65646fbfc55 100644 --- a/Common/Core/vtkObjectFactory.h +++ b/Common/Core/vtkObjectFactory.h @@ -66,8 +66,10 @@ class VTKCOMMONCORE_EXPORT vtkObjectFactory : public vtkObject /** * No longer used. Call vtkObjectBase::InitializeObjectBase() from the * New() implementation instead. + * @deprecated because this method relies on taking an arbitrary string, + * which may not match the GetClassName() string (especially for templates). */ - static void ConstructInstance(const char* vtkclassname); + VTK_LEGACY(static void ConstructInstance(const char* vtkclassname)); /** * Create all possible instances of the named vtk object. From cd06ce09ac6fb33f4321d0ff121147fcad5beb42 Mon Sep 17 00:00:00 2001 From: "David C. Lonie" Date: Wed, 28 Sep 2016 15:58:37 -0400 Subject: [PATCH 3/3] Add Schwartz counters for consistent static destruction. Static builds of paraview were not freeing vtkObjectFactory::RegisteredFactories or vtkOutputWindow::Instance. See: https://open.cdash.org/viewTest.php?onlyfailed&buildid=4572721 This fixes the issue to ensure that they are always freed at process exit. --- Common/Core/vtkObjectFactory.cxx | 21 +++++++++------------ Common/Core/vtkObjectFactory.h | 15 +++++++++++++++ Common/Core/vtkOutputWindow.cxx | 13 +++++++------ Common/Core/vtkOutputWindow.h | 10 +++++----- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/Common/Core/vtkObjectFactory.cxx b/Common/Core/vtkObjectFactory.cxx index 28da26091b0..ad8abe7f5e2 100644 --- a/Common/Core/vtkObjectFactory.cxx +++ b/Common/Core/vtkObjectFactory.cxx @@ -27,21 +27,20 @@ vtkObjectFactoryCollection* vtkObjectFactory::RegisteredFactories = 0; +static unsigned int vtkObjectFactoryRegistryCleanupCounter = 0; +vtkObjectFactoryRegistryCleanup::vtkObjectFactoryRegistryCleanup() +{ + ++vtkObjectFactoryRegistryCleanupCounter; +} -class vtkCleanUpObjectFactory +vtkObjectFactoryRegistryCleanup::~vtkObjectFactoryRegistryCleanup() { -public: - inline void Use() - { - } - ~vtkCleanUpObjectFactory() + if (--vtkObjectFactoryRegistryCleanupCounter == 0) { - vtkObjectFactory::UnRegisterAllFactories(); + vtkObjectFactory::UnRegisterAllFactories(); } -}; - -static vtkCleanUpObjectFactory vtkCleanUpObjectFactoryGlobal; +} // Create an instance of a named vtk object using the loaded // factories @@ -88,7 +87,6 @@ void vtkObjectFactory::ConstructInstance(const char *vtkclassname) // A one time initialization method. void vtkObjectFactory::Init() { - vtkCleanUpObjectFactoryGlobal.Use(); // Don't do anything if we are already initialized if(vtkObjectFactory::RegisteredFactories) { @@ -737,4 +735,3 @@ void vtkObjectFactory::CreateAllInstance(const char* vtkclassname, } } } - diff --git a/Common/Core/vtkObjectFactory.h b/Common/Core/vtkObjectFactory.h index 65646fbfc55..c82c56c8661 100644 --- a/Common/Core/vtkObjectFactory.h +++ b/Common/Core/vtkObjectFactory.h @@ -38,6 +38,7 @@ #ifndef vtkObjectFactory_h #define vtkObjectFactory_h +#include "vtkDebugLeaksManager.h" // Must be included before singletons #include "vtkCommonCoreModule.h" // For export macro #include "vtkObject.h" @@ -286,6 +287,20 @@ class VTKCOMMONCORE_EXPORT vtkObjectFactory : public vtkObject void operator=(const vtkObjectFactory&) VTK_DELETE_FUNCTION; }; +// Implementation detail for Schwartz counter idiom. +class VTKCOMMONCORE_EXPORT vtkObjectFactoryRegistryCleanup +{ +public: + vtkObjectFactoryRegistryCleanup(); + ~vtkObjectFactoryRegistryCleanup(); + +private: + vtkObjectFactoryRegistryCleanup(const vtkObjectFactoryRegistryCleanup& other) VTK_DELETE_FUNCTION; + vtkObjectFactoryRegistryCleanup& operator=(const vtkObjectFactoryRegistryCleanup& rhs) VTK_DELETE_FUNCTION; +}; +static vtkObjectFactoryRegistryCleanup vtkObjectFactoryRegistryCleanupInstance; + + // Macro to create an object creation function. // The name of the function will by vtkObjectFactoryCreateclassname // where classname is the name of the class being created diff --git a/Common/Core/vtkOutputWindow.cxx b/Common/Core/vtkOutputWindow.cxx index b2e970b10b0..d0f6c9294a8 100644 --- a/Common/Core/vtkOutputWindow.cxx +++ b/Common/Core/vtkOutputWindow.cxx @@ -22,13 +22,10 @@ #endif #include "vtkCommand.h" #include "vtkObjectFactory.h" -#include "vtkDebugLeaks.h" - //---------------------------------------------------------------------------- - vtkOutputWindow* vtkOutputWindow::Instance = 0; -vtkOutputWindowCleanup vtkOutputWindow::Cleanup; +static unsigned int vtkOutputWindowCleanupCounter = 0; void vtkOutputWindowDisplayText(const char* message) { @@ -57,12 +54,16 @@ void vtkOutputWindowDisplayDebugText(const char* message) vtkOutputWindowCleanup::vtkOutputWindowCleanup() { + ++vtkOutputWindowCleanupCounter; } vtkOutputWindowCleanup::~vtkOutputWindowCleanup() { - // Destroy any remaining output window. - vtkOutputWindow::SetInstance(0); + if (--vtkOutputWindowCleanupCounter == 0) + { + // Destroy any remaining output window. + vtkOutputWindow::SetInstance(0); + } } vtkOutputWindow::vtkOutputWindow() diff --git a/Common/Core/vtkOutputWindow.h b/Common/Core/vtkOutputWindow.h index 1f1f9d21839..5c590138262 100644 --- a/Common/Core/vtkOutputWindow.h +++ b/Common/Core/vtkOutputWindow.h @@ -25,6 +25,7 @@ #ifndef vtkOutputWindow_h #define vtkOutputWindow_h +#include "vtkDebugLeaksManager.h" // Must be included before singletons #include "vtkCommonCoreModule.h" // For export macro #include "vtkObject.h" @@ -89,11 +90,6 @@ class VTKCOMMONCORE_EXPORT vtkOutputWindow : public vtkObject vtkSetMacro(PromptUser, int); //@} - // use this as a way of memory management when the - // program exits the SmartPointer will be deleted which - // will delete the Instance singleton - static vtkOutputWindowCleanup Cleanup; - protected: vtkOutputWindow(); ~vtkOutputWindow() VTK_OVERRIDE; @@ -105,4 +101,8 @@ class VTKCOMMONCORE_EXPORT vtkOutputWindow : public vtkObject void operator=(const vtkOutputWindow&) VTK_DELETE_FUNCTION; }; +// Uses schwartz counter idiom for singleton management +static vtkOutputWindowCleanup vtkOutputWindowCleanupInstance; + + #endif