diff --git a/src/actions.cpp b/src/actions.cpp index 53e21b7f..f2eb9d11 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -114,6 +114,18 @@ namespace Action { return *instance_; } // TaskFactory::instance + void TaskFactory::cleanup() + { + if (instance_ != 0) { + Registry::iterator e = registry_.end(); + for (Registry::iterator i = registry_.begin(); i != e; ++i) { + delete i->second; + } + delete instance_; + instance_ = 0; + } + } //TaskFactory::cleanup + void TaskFactory::registerTask(TaskType type, Task::AutoPtr task) { Registry::iterator i = registry_.find(type); diff --git a/src/actions.hpp b/src/actions.hpp index 593122a5..6a932056 100644 --- a/src/actions.hpp +++ b/src/actions.hpp @@ -107,6 +107,8 @@ namespace Action { this method. */ static TaskFactory& instance(); + //! Destructor + void cleanup(); /*! @brief Create a task. diff --git a/src/exiv2.cpp b/src/exiv2.cpp index 98d0e3df..c97e069b 100644 --- a/src/exiv2.cpp +++ b/src/exiv2.cpp @@ -142,6 +142,10 @@ int main(int argc, char* const argv[]) } task->run(*i); } + + taskFactory.cleanup(); + params.cleanup(); + return 0; } // main @@ -157,6 +161,12 @@ Params& Params::instance() return *instance_; } +void Params::cleanup() +{ + delete instance_; + instance_ = 0; +} + void Params::version(std::ostream& os) const { os << EXV_PACKAGE_STRING << ", " diff --git a/src/exiv2.hpp b/src/exiv2.hpp index 17d388cd..dbdbc1a4 100644 --- a/src/exiv2.hpp +++ b/src/exiv2.hpp @@ -119,6 +119,8 @@ public: @return Reference to the global Params instance. */ static Params& instance(); + //! Destructor + void cleanup(); //! Enumerates print modes enum PrintMode { pmSummary, pmInterpreted, pmValues, pmHexdump, pmIptc, diff --git a/src/image.cpp b/src/image.cpp index 64595955..3934700d 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -66,8 +66,28 @@ EXIV2_RCSID("@(#) $Id$"); // class member definitions namespace Exiv2 { + int ImageFactory::Init::count = 0; + + ImageFactory::Init::Init() + { + ++count; + } + + ImageFactory::Init::~Init() + { + if (--count == 0) { + Exiv2::ImageFactory::cleanup(); + } + } + ImageFactory::Registry* ImageFactory::registry_ = 0; + void ImageFactory::cleanup() + { + delete registry_; + registry_ = 0; + } + void ImageFactory::init() { if (0 == registry_) { diff --git a/src/image.hpp b/src/image.hpp index ae7a43bb..f6343e57 100644 --- a/src/image.hpp +++ b/src/image.hpp @@ -252,6 +252,8 @@ namespace Exiv2 { public: //! @name Manipulators //@{ + //! Destructor. + static void cleanup(); /*! @brief Register image type together with its function pointers. @@ -372,6 +374,24 @@ namespace Exiv2 { static Image::Type getType(BasicIo& io); //@} + /*! + @brief Class Init is used to execute initialisation and termination + code exactly once, at the begin and end of the program. + + See Bjarne Stroustrup, 'The C++ Programming Language 3rd + Edition', section 21.5.2 for details about this pattern. + */ + class Init { + static int count; //!< Counts calls to constructor + public: + //! @name Creators + //@{ + //! Perform one-time initialisations. + Init(); + //! Perform one-time cleanup operations. + ~Init(); + //@} + }; private: //! @name Creators @@ -458,4 +478,16 @@ namespace Exiv2 { } // namespace Exiv2 +namespace { + /*! + Each translation unit that includes image.hpp declares its own + Init object. The destructor ensures that the factory is properly + freed exactly once. + + See Bjarne Stroustrup, 'The C++ Programming Language 3rd + Edition', section 21.5.2 for details about this pattern. + */ + Exiv2::ImageFactory::Init imageFactoryInit; +} + #endif // #ifndef IMAGE_HPP_ diff --git a/src/makernote.cpp b/src/makernote.cpp index b807917a..d792d54d 100644 --- a/src/makernote.cpp +++ b/src/makernote.cpp @@ -184,9 +184,42 @@ namespace Exiv2 { return AutoPtr(clone_()); } + int MakerNoteFactory::Init::count = 0; + + MakerNoteFactory::Init::Init() + { + ++count; + } + + MakerNoteFactory::Init::~Init() + { + if (--count == 0) { + Exiv2::MakerNoteFactory::cleanup(); + } + } + MakerNoteFactory::Registry* MakerNoteFactory::pRegistry_ = 0; MakerNoteFactory::IfdIdRegistry* MakerNoteFactory::pIfdIdRegistry_ = 0; + void MakerNoteFactory::cleanup() + { + if (pRegistry_ != 0) { + Registry::iterator e = pRegistry_->end(); + for (Registry::iterator i = pRegistry_->begin(); i != e; ++i) { + delete i->second; + } + delete pRegistry_; + } + + if (pIfdIdRegistry_ != 0) { + IfdIdRegistry::iterator e = pIfdIdRegistry_->end(); + for (IfdIdRegistry::iterator i = pIfdIdRegistry_->begin(); i != e; ++i) { + delete i->second; + } + delete pIfdIdRegistry_; + } + } + void MakerNoteFactory::init() { if (0 == pRegistry_) { @@ -203,6 +236,11 @@ namespace Exiv2 { init(); MakerNote* pMakerNote = makerNote.release(); assert(pMakerNote); + IfdIdRegistry::iterator pos = pIfdIdRegistry_->find(ifdId); + if (pos != pIfdIdRegistry_->end()) { + delete pos->second; + pos->second = 0; + } (*pIfdIdRegistry_)[ifdId] = pMakerNote; } // MakerNoteFactory::registerMakerNote diff --git a/src/makernote.hpp b/src/makernote.hpp index a604c159..d792f506 100644 --- a/src/makernote.hpp +++ b/src/makernote.hpp @@ -344,6 +344,8 @@ namespace Exiv2 { */ class MakerNoteFactory { public: + //! Destructor. + static void cleanup(); /*! @brief Register a %MakerNote create function for a camera make and model. @@ -442,6 +444,25 @@ namespace Exiv2 { */ static int match(const std::string& regEntry, const std::string& key); + /*! + @brief Class Init is used to execute initialisation and termination + code exactly once, at the begin and end of the program. + + See Bjarne Stroustrup, 'The C++ Programming Language 3rd + Edition', section 21.5.2 for details about this pattern. + */ + class Init { + static int count; //!< Counts calls to constructor + public: + //! @name Creators + //@{ + //! Perform one-time initialisations. + Init(); + //! Perform one-time cleanup operations. + ~Init(); + //@} + }; + private: //! @name Creators //@{ @@ -471,4 +492,16 @@ namespace Exiv2 { } // namespace Exiv2 +namespace { + /*! + Each translation unit that includes makernote.hpp declares its own + Init object. The destructor ensures that the factory is properly + freed exactly once. + + See Bjarne Stroustrup, 'The C++ Programming Language 3rd + Edition', section 21.5.2 for details about this pattern. + */ + Exiv2::MakerNoteFactory::Init makerNoteFactoryInit; +} + #endif // #ifndef MAKERNOTE_HPP_