Store inner exceptions with shared_ptr rather than a bare pointer so that the inner exception survives copies

Originally committed to SVN as r4714.
This commit is contained in:
Thomas Goyne 2010-07-27 03:52:32 +00:00
parent e2d9241efd
commit 6407e36c87

View file

@ -37,6 +37,11 @@
#pragma once #pragma once
#include <string> #include <string>
#ifdef _WIN32
#include <memory>
#else
#include <tr1/memory>
#endif
/// @see aegisub.h /// @see aegisub.h
namespace agi { namespace agi {
@ -96,7 +101,7 @@ namespace agi {
std::string message; std::string message;
/// An inner exception, the cause of this exception /// An inner exception, the cause of this exception
Exception *inner; std::tr1::shared_ptr<Exception> inner;
protected: protected:
@ -108,10 +113,9 @@ namespace agi {
/// the base class. /// the base class.
Exception(const std::string &msg, const Exception *inr = 0) Exception(const std::string &msg, const Exception *inr = 0)
: message(msg) : message(msg)
, inner(0)
{ {
if (inr) if (inr)
inner = inr->Copy(); inner.reset(inr->Copy());
} }
/// @brief Default constructor, not implemented /// @brief Default constructor, not implemented
@ -120,17 +124,12 @@ namespace agi {
/// as it leaves the members un-initialised. /// as it leaves the members un-initialised.
Exception(); Exception();
public:
/// @brief Destructor /// @brief Destructor
///
/// The inner exception is expected to have been duplicated in our constructor
/// and thus be owned by us.
virtual ~Exception() virtual ~Exception()
{ {
delete inner;
} }
public:
/// @brief Get the outer exception error message /// @brief Get the outer exception error message
/// @return Error message /// @return Error message
virtual std::string GetMessage() const { return message; } virtual std::string GetMessage() const { return message; }
@ -141,7 +140,7 @@ namespace agi {
/// If there is an inner exception, prepend its chained error message to /// If there is an inner exception, prepend its chained error message to
/// our error message, with a CRLF between. Returns our own error message /// our error message, with a CRLF between. Returns our own error message
/// alone if there is no inner exception. /// alone if there is no inner exception.
std::string GetChainedMessage() const { if (inner) return inner->GetChainedMessage() + "\r\n" + GetMessage(); else return GetMessage(); } std::string GetChainedMessage() const { if (inner.get()) return inner->GetChainedMessage() + "\r\n" + GetMessage(); else return GetMessage(); }
/// @brief Exception class printable name /// @brief Exception class printable name
/// ///
@ -294,7 +293,7 @@ namespace agi {
const char * GetName() const { return "filesystem/not_accessible/not_found"; } const char * GetName() const { return "filesystem/not_accessible/not_found"; }
// Not documented, see Aegisub::Exception class // Not documented, see Aegisub::Exception class
Exception * Copy() const { return new FileNotFoundError(*this); } \ Exception * Copy() const { return new FileNotFoundError(*this); }
}; };