Custom C++ exception class with stack trace generation

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
1
down vote

favorite
1












I wanted to implement my own runtime error class in C++, that could provide more meaningful information on where the error occurred than std::runtime_error does.



I decided to use boost::stacktrace to generate a stack trace, appended to the exception message.



Anyway, this is my code:



/**
brief Represents a runtime error.

Equivalent of std::runtime_error, but contains a stacktrace
generated by Boost.
*/
class Exception : public std::runtime_error

public:
/**
brief Returns error description.

If the backtrace was generated successfully,
returns the message along with stack trace.
Otherwise, behaves like std::runtime_error::what().
*/
const char *what( ) const noexcept override

if ( has_backtrace )
return message.c_str( );
else
return std::runtime_error::what( );


/**
brief Constructs an exception, generates a backtrace if possible.

param cmessage The error description.
*/
Exception( const char *cmessage ) :
std::runtime_error( cmessage ) // std::runtime_error will store the original message

// Attempt to generate stacktrace
try

std::stringstream buffer;
buffer << cmessage << std::endl << boost::stacktrace::stacktrace( );
message = buffer.str( );
has_backtrace = true;

catch ( std::exception &ex )

has_backtrace = false;



protected:
bool has_backtrace; //!< Determines if backtrace is present
std::string message; //!< Contains the user message along with backtrace.
;


I can tell it works on this simple example



void foo( )

throw Exception( "some message" );


void bar( )

foo( );


int main( )

try

bar( );

catch ( std::exception &ex )

std::cerr << ex.what( );


return 0;



because it generates following message:



some message
0# Exception::Exception(char const*) in ./ex
1# foo() in ./ex
2# bar() in ./ex
3# main in ./ex
4# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
5# _start in ./ex


However, what I'd like to know is if my code isn't too complicated
as for an exception class and if it properly handles possible stack trace
generator exceptions and properly falls back to std::runtime_error functionality.



Also, is there some important property/method that all exception classes should have, that I had overlooked and forgot to implement? Maybe the whole idea of having such class is bad in general and I should use some other solution?



Other suggestions are obviously welcome too.










share|improve this question









New contributor




Jacajack is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

























    up vote
    1
    down vote

    favorite
    1












    I wanted to implement my own runtime error class in C++, that could provide more meaningful information on where the error occurred than std::runtime_error does.



    I decided to use boost::stacktrace to generate a stack trace, appended to the exception message.



    Anyway, this is my code:



    /**
    brief Represents a runtime error.

    Equivalent of std::runtime_error, but contains a stacktrace
    generated by Boost.
    */
    class Exception : public std::runtime_error

    public:
    /**
    brief Returns error description.

    If the backtrace was generated successfully,
    returns the message along with stack trace.
    Otherwise, behaves like std::runtime_error::what().
    */
    const char *what( ) const noexcept override

    if ( has_backtrace )
    return message.c_str( );
    else
    return std::runtime_error::what( );


    /**
    brief Constructs an exception, generates a backtrace if possible.

    param cmessage The error description.
    */
    Exception( const char *cmessage ) :
    std::runtime_error( cmessage ) // std::runtime_error will store the original message

    // Attempt to generate stacktrace
    try

    std::stringstream buffer;
    buffer << cmessage << std::endl << boost::stacktrace::stacktrace( );
    message = buffer.str( );
    has_backtrace = true;

    catch ( std::exception &ex )

    has_backtrace = false;



    protected:
    bool has_backtrace; //!< Determines if backtrace is present
    std::string message; //!< Contains the user message along with backtrace.
    ;


    I can tell it works on this simple example



    void foo( )

    throw Exception( "some message" );


    void bar( )

    foo( );


    int main( )

    try

    bar( );

    catch ( std::exception &ex )

    std::cerr << ex.what( );


    return 0;



    because it generates following message:



    some message
    0# Exception::Exception(char const*) in ./ex
    1# foo() in ./ex
    2# bar() in ./ex
    3# main in ./ex
    4# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
    5# _start in ./ex


    However, what I'd like to know is if my code isn't too complicated
    as for an exception class and if it properly handles possible stack trace
    generator exceptions and properly falls back to std::runtime_error functionality.



    Also, is there some important property/method that all exception classes should have, that I had overlooked and forgot to implement? Maybe the whole idea of having such class is bad in general and I should use some other solution?



    Other suggestions are obviously welcome too.










    share|improve this question









    New contributor




    Jacajack is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.





















      up vote
      1
      down vote

      favorite
      1









      up vote
      1
      down vote

      favorite
      1






      1





      I wanted to implement my own runtime error class in C++, that could provide more meaningful information on where the error occurred than std::runtime_error does.



      I decided to use boost::stacktrace to generate a stack trace, appended to the exception message.



      Anyway, this is my code:



      /**
      brief Represents a runtime error.

      Equivalent of std::runtime_error, but contains a stacktrace
      generated by Boost.
      */
      class Exception : public std::runtime_error

      public:
      /**
      brief Returns error description.

      If the backtrace was generated successfully,
      returns the message along with stack trace.
      Otherwise, behaves like std::runtime_error::what().
      */
      const char *what( ) const noexcept override

      if ( has_backtrace )
      return message.c_str( );
      else
      return std::runtime_error::what( );


      /**
      brief Constructs an exception, generates a backtrace if possible.

      param cmessage The error description.
      */
      Exception( const char *cmessage ) :
      std::runtime_error( cmessage ) // std::runtime_error will store the original message

      // Attempt to generate stacktrace
      try

      std::stringstream buffer;
      buffer << cmessage << std::endl << boost::stacktrace::stacktrace( );
      message = buffer.str( );
      has_backtrace = true;

      catch ( std::exception &ex )

      has_backtrace = false;



      protected:
      bool has_backtrace; //!< Determines if backtrace is present
      std::string message; //!< Contains the user message along with backtrace.
      ;


      I can tell it works on this simple example



      void foo( )

      throw Exception( "some message" );


      void bar( )

      foo( );


      int main( )

      try

      bar( );

      catch ( std::exception &ex )

      std::cerr << ex.what( );


      return 0;



      because it generates following message:



      some message
      0# Exception::Exception(char const*) in ./ex
      1# foo() in ./ex
      2# bar() in ./ex
      3# main in ./ex
      4# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
      5# _start in ./ex


      However, what I'd like to know is if my code isn't too complicated
      as for an exception class and if it properly handles possible stack trace
      generator exceptions and properly falls back to std::runtime_error functionality.



      Also, is there some important property/method that all exception classes should have, that I had overlooked and forgot to implement? Maybe the whole idea of having such class is bad in general and I should use some other solution?



      Other suggestions are obviously welcome too.










      share|improve this question









      New contributor




      Jacajack is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      I wanted to implement my own runtime error class in C++, that could provide more meaningful information on where the error occurred than std::runtime_error does.



      I decided to use boost::stacktrace to generate a stack trace, appended to the exception message.



      Anyway, this is my code:



      /**
      brief Represents a runtime error.

      Equivalent of std::runtime_error, but contains a stacktrace
      generated by Boost.
      */
      class Exception : public std::runtime_error

      public:
      /**
      brief Returns error description.

      If the backtrace was generated successfully,
      returns the message along with stack trace.
      Otherwise, behaves like std::runtime_error::what().
      */
      const char *what( ) const noexcept override

      if ( has_backtrace )
      return message.c_str( );
      else
      return std::runtime_error::what( );


      /**
      brief Constructs an exception, generates a backtrace if possible.

      param cmessage The error description.
      */
      Exception( const char *cmessage ) :
      std::runtime_error( cmessage ) // std::runtime_error will store the original message

      // Attempt to generate stacktrace
      try

      std::stringstream buffer;
      buffer << cmessage << std::endl << boost::stacktrace::stacktrace( );
      message = buffer.str( );
      has_backtrace = true;

      catch ( std::exception &ex )

      has_backtrace = false;



      protected:
      bool has_backtrace; //!< Determines if backtrace is present
      std::string message; //!< Contains the user message along with backtrace.
      ;


      I can tell it works on this simple example



      void foo( )

      throw Exception( "some message" );


      void bar( )

      foo( );


      int main( )

      try

      bar( );

      catch ( std::exception &ex )

      std::cerr << ex.what( );


      return 0;



      because it generates following message:



      some message
      0# Exception::Exception(char const*) in ./ex
      1# foo() in ./ex
      2# bar() in ./ex
      3# main in ./ex
      4# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
      5# _start in ./ex


      However, what I'd like to know is if my code isn't too complicated
      as for an exception class and if it properly handles possible stack trace
      generator exceptions and properly falls back to std::runtime_error functionality.



      Also, is there some important property/method that all exception classes should have, that I had overlooked and forgot to implement? Maybe the whole idea of having such class is bad in general and I should use some other solution?



      Other suggestions are obviously welcome too.







      c++ error-handling exception






      share|improve this question









      New contributor




      Jacajack is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      Jacajack is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 1 hour ago









      Deduplicator

      10.4k1849




      10.4k1849






      New contributor




      Jacajack is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 3 hours ago









      Jacajack

      1084




      1084




      New contributor




      Jacajack is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Jacajack is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Jacajack is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          3
          down vote



          accepted










          Exception( const char *cmessage ) :


          I strongly recommend making this constructor explicit, so that you don't permit the user to accidentally write



          void some_function(const Exception&);
          ...
          some_function("hello world");


          My impression is that most C++ experts recommend explicit on one-argument constructors; I personally hold the minority opinion that explicit should be present on all constructors by default (i.e., if you don't have a specific immediate need for implicit conversion, you should just put explicit automatically, and sort out the consequences later if necessary).




          catch ( std::exception &ex )


          My current employer's codebase actually does catch by non-const reference, but if you're starting from scratch, I strongly recommend catching by const reference by default. Accidentally mutating the current exception object can cause race conditions.




          Also, in the Exception constructor, your catch (std::exception&) should almost certainly be catch (...), right?




          As for the high-level point of what you're doing, I believe I have an outline of this sort of thing under "Mix-Ins" somewhere near the end of Template Normal Programming. (Sorry, I'm rushed right now, but I can come back and give you a real link later.)



          The first improvement is to make your thing a template inheriting from T instead of from std::runtime_error specifically. Second, I'd make a function my::throw_with_stacktrace(T&& ex) that simply does throw Exception<std::remove_reference_t<T>>(std::forward<T>(ex));.



          Gotta run, but I hope this helps a bit.






          share|improve this answer




















          • Thanks for quick response. I'm relatively new to C++ (I've been using pure C extensively before), so I figured out that the best way to learn is by starting some C++ project and facing the real issues in practice. I really appreciate the learning resources. I believe the rvalue references and more advanced template stuff are something that I definitely need to dive more into, because I don't really get them. Your answer is really helpful to me, because now I see an actual use for these concepts. Again, thank you for help.
            – Jacajack
            1 hour ago

















          up vote
          2
          down vote













          1. It's very surprising that your custom exception-class can throw an exception for anything but original creation. std::exception and derived standard classes aren't allowed to do that.


          2. Is it actually significant whether the object stores a stack-trace at all? Most likely not. So, consider simply modifying the passed message instead of creating your own classes. That calls for a (potentially templated) function instead.


          3. As-is, you store the original message, and then try to store the enhanced message and a flag that the enhanced message exists (which is equivalent to not being empty, so why a flag???) and should be used instead. That's a waste.






          share|improve this answer






















          • I'm sorry, but I don't think I understand the 1st point. Do you mean the lack of noexcept specifier alongside the constructors and assignment operator? If not, could you elaborate, please?
            – Jacajack
            1 hour ago






          • 1




            I mean that the copy- ctor/assignment can throw, as the std::string-member may need to allocate memory. But do you really want to upgrade it from throw std::bad_alloc; to std::terminate(), instead of going the COW-route?
            – Deduplicator
            46 mins ago










          • Alright, I see. I didn't think of that. As you said, the dedicated throw function seems like a much better solution now. Thanks for help.
            – Jacajack
            38 mins ago










          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );






          Jacajack is a new contributor. Be nice, and check out our Code of Conduct.









           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f203823%2fcustom-c-exception-class-with-stack-trace-generation%23new-answer', 'question_page');

          );

          Post as a guest






























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          3
          down vote



          accepted










          Exception( const char *cmessage ) :


          I strongly recommend making this constructor explicit, so that you don't permit the user to accidentally write



          void some_function(const Exception&);
          ...
          some_function("hello world");


          My impression is that most C++ experts recommend explicit on one-argument constructors; I personally hold the minority opinion that explicit should be present on all constructors by default (i.e., if you don't have a specific immediate need for implicit conversion, you should just put explicit automatically, and sort out the consequences later if necessary).




          catch ( std::exception &ex )


          My current employer's codebase actually does catch by non-const reference, but if you're starting from scratch, I strongly recommend catching by const reference by default. Accidentally mutating the current exception object can cause race conditions.




          Also, in the Exception constructor, your catch (std::exception&) should almost certainly be catch (...), right?




          As for the high-level point of what you're doing, I believe I have an outline of this sort of thing under "Mix-Ins" somewhere near the end of Template Normal Programming. (Sorry, I'm rushed right now, but I can come back and give you a real link later.)



          The first improvement is to make your thing a template inheriting from T instead of from std::runtime_error specifically. Second, I'd make a function my::throw_with_stacktrace(T&& ex) that simply does throw Exception<std::remove_reference_t<T>>(std::forward<T>(ex));.



          Gotta run, but I hope this helps a bit.






          share|improve this answer




















          • Thanks for quick response. I'm relatively new to C++ (I've been using pure C extensively before), so I figured out that the best way to learn is by starting some C++ project and facing the real issues in practice. I really appreciate the learning resources. I believe the rvalue references and more advanced template stuff are something that I definitely need to dive more into, because I don't really get them. Your answer is really helpful to me, because now I see an actual use for these concepts. Again, thank you for help.
            – Jacajack
            1 hour ago














          up vote
          3
          down vote



          accepted










          Exception( const char *cmessage ) :


          I strongly recommend making this constructor explicit, so that you don't permit the user to accidentally write



          void some_function(const Exception&);
          ...
          some_function("hello world");


          My impression is that most C++ experts recommend explicit on one-argument constructors; I personally hold the minority opinion that explicit should be present on all constructors by default (i.e., if you don't have a specific immediate need for implicit conversion, you should just put explicit automatically, and sort out the consequences later if necessary).




          catch ( std::exception &ex )


          My current employer's codebase actually does catch by non-const reference, but if you're starting from scratch, I strongly recommend catching by const reference by default. Accidentally mutating the current exception object can cause race conditions.




          Also, in the Exception constructor, your catch (std::exception&) should almost certainly be catch (...), right?




          As for the high-level point of what you're doing, I believe I have an outline of this sort of thing under "Mix-Ins" somewhere near the end of Template Normal Programming. (Sorry, I'm rushed right now, but I can come back and give you a real link later.)



          The first improvement is to make your thing a template inheriting from T instead of from std::runtime_error specifically. Second, I'd make a function my::throw_with_stacktrace(T&& ex) that simply does throw Exception<std::remove_reference_t<T>>(std::forward<T>(ex));.



          Gotta run, but I hope this helps a bit.






          share|improve this answer




















          • Thanks for quick response. I'm relatively new to C++ (I've been using pure C extensively before), so I figured out that the best way to learn is by starting some C++ project and facing the real issues in practice. I really appreciate the learning resources. I believe the rvalue references and more advanced template stuff are something that I definitely need to dive more into, because I don't really get them. Your answer is really helpful to me, because now I see an actual use for these concepts. Again, thank you for help.
            – Jacajack
            1 hour ago












          up vote
          3
          down vote



          accepted







          up vote
          3
          down vote



          accepted






          Exception( const char *cmessage ) :


          I strongly recommend making this constructor explicit, so that you don't permit the user to accidentally write



          void some_function(const Exception&);
          ...
          some_function("hello world");


          My impression is that most C++ experts recommend explicit on one-argument constructors; I personally hold the minority opinion that explicit should be present on all constructors by default (i.e., if you don't have a specific immediate need for implicit conversion, you should just put explicit automatically, and sort out the consequences later if necessary).




          catch ( std::exception &ex )


          My current employer's codebase actually does catch by non-const reference, but if you're starting from scratch, I strongly recommend catching by const reference by default. Accidentally mutating the current exception object can cause race conditions.




          Also, in the Exception constructor, your catch (std::exception&) should almost certainly be catch (...), right?




          As for the high-level point of what you're doing, I believe I have an outline of this sort of thing under "Mix-Ins" somewhere near the end of Template Normal Programming. (Sorry, I'm rushed right now, but I can come back and give you a real link later.)



          The first improvement is to make your thing a template inheriting from T instead of from std::runtime_error specifically. Second, I'd make a function my::throw_with_stacktrace(T&& ex) that simply does throw Exception<std::remove_reference_t<T>>(std::forward<T>(ex));.



          Gotta run, but I hope this helps a bit.






          share|improve this answer












          Exception( const char *cmessage ) :


          I strongly recommend making this constructor explicit, so that you don't permit the user to accidentally write



          void some_function(const Exception&);
          ...
          some_function("hello world");


          My impression is that most C++ experts recommend explicit on one-argument constructors; I personally hold the minority opinion that explicit should be present on all constructors by default (i.e., if you don't have a specific immediate need for implicit conversion, you should just put explicit automatically, and sort out the consequences later if necessary).




          catch ( std::exception &ex )


          My current employer's codebase actually does catch by non-const reference, but if you're starting from scratch, I strongly recommend catching by const reference by default. Accidentally mutating the current exception object can cause race conditions.




          Also, in the Exception constructor, your catch (std::exception&) should almost certainly be catch (...), right?




          As for the high-level point of what you're doing, I believe I have an outline of this sort of thing under "Mix-Ins" somewhere near the end of Template Normal Programming. (Sorry, I'm rushed right now, but I can come back and give you a real link later.)



          The first improvement is to make your thing a template inheriting from T instead of from std::runtime_error specifically. Second, I'd make a function my::throw_with_stacktrace(T&& ex) that simply does throw Exception<std::remove_reference_t<T>>(std::forward<T>(ex));.



          Gotta run, but I hope this helps a bit.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 1 hour ago









          Quuxplusone

          10.3k11853




          10.3k11853











          • Thanks for quick response. I'm relatively new to C++ (I've been using pure C extensively before), so I figured out that the best way to learn is by starting some C++ project and facing the real issues in practice. I really appreciate the learning resources. I believe the rvalue references and more advanced template stuff are something that I definitely need to dive more into, because I don't really get them. Your answer is really helpful to me, because now I see an actual use for these concepts. Again, thank you for help.
            – Jacajack
            1 hour ago
















          • Thanks for quick response. I'm relatively new to C++ (I've been using pure C extensively before), so I figured out that the best way to learn is by starting some C++ project and facing the real issues in practice. I really appreciate the learning resources. I believe the rvalue references and more advanced template stuff are something that I definitely need to dive more into, because I don't really get them. Your answer is really helpful to me, because now I see an actual use for these concepts. Again, thank you for help.
            – Jacajack
            1 hour ago















          Thanks for quick response. I'm relatively new to C++ (I've been using pure C extensively before), so I figured out that the best way to learn is by starting some C++ project and facing the real issues in practice. I really appreciate the learning resources. I believe the rvalue references and more advanced template stuff are something that I definitely need to dive more into, because I don't really get them. Your answer is really helpful to me, because now I see an actual use for these concepts. Again, thank you for help.
          – Jacajack
          1 hour ago




          Thanks for quick response. I'm relatively new to C++ (I've been using pure C extensively before), so I figured out that the best way to learn is by starting some C++ project and facing the real issues in practice. I really appreciate the learning resources. I believe the rvalue references and more advanced template stuff are something that I definitely need to dive more into, because I don't really get them. Your answer is really helpful to me, because now I see an actual use for these concepts. Again, thank you for help.
          – Jacajack
          1 hour ago












          up vote
          2
          down vote













          1. It's very surprising that your custom exception-class can throw an exception for anything but original creation. std::exception and derived standard classes aren't allowed to do that.


          2. Is it actually significant whether the object stores a stack-trace at all? Most likely not. So, consider simply modifying the passed message instead of creating your own classes. That calls for a (potentially templated) function instead.


          3. As-is, you store the original message, and then try to store the enhanced message and a flag that the enhanced message exists (which is equivalent to not being empty, so why a flag???) and should be used instead. That's a waste.






          share|improve this answer






















          • I'm sorry, but I don't think I understand the 1st point. Do you mean the lack of noexcept specifier alongside the constructors and assignment operator? If not, could you elaborate, please?
            – Jacajack
            1 hour ago






          • 1




            I mean that the copy- ctor/assignment can throw, as the std::string-member may need to allocate memory. But do you really want to upgrade it from throw std::bad_alloc; to std::terminate(), instead of going the COW-route?
            – Deduplicator
            46 mins ago










          • Alright, I see. I didn't think of that. As you said, the dedicated throw function seems like a much better solution now. Thanks for help.
            – Jacajack
            38 mins ago














          up vote
          2
          down vote













          1. It's very surprising that your custom exception-class can throw an exception for anything but original creation. std::exception and derived standard classes aren't allowed to do that.


          2. Is it actually significant whether the object stores a stack-trace at all? Most likely not. So, consider simply modifying the passed message instead of creating your own classes. That calls for a (potentially templated) function instead.


          3. As-is, you store the original message, and then try to store the enhanced message and a flag that the enhanced message exists (which is equivalent to not being empty, so why a flag???) and should be used instead. That's a waste.






          share|improve this answer






















          • I'm sorry, but I don't think I understand the 1st point. Do you mean the lack of noexcept specifier alongside the constructors and assignment operator? If not, could you elaborate, please?
            – Jacajack
            1 hour ago






          • 1




            I mean that the copy- ctor/assignment can throw, as the std::string-member may need to allocate memory. But do you really want to upgrade it from throw std::bad_alloc; to std::terminate(), instead of going the COW-route?
            – Deduplicator
            46 mins ago










          • Alright, I see. I didn't think of that. As you said, the dedicated throw function seems like a much better solution now. Thanks for help.
            – Jacajack
            38 mins ago












          up vote
          2
          down vote










          up vote
          2
          down vote









          1. It's very surprising that your custom exception-class can throw an exception for anything but original creation. std::exception and derived standard classes aren't allowed to do that.


          2. Is it actually significant whether the object stores a stack-trace at all? Most likely not. So, consider simply modifying the passed message instead of creating your own classes. That calls for a (potentially templated) function instead.


          3. As-is, you store the original message, and then try to store the enhanced message and a flag that the enhanced message exists (which is equivalent to not being empty, so why a flag???) and should be used instead. That's a waste.






          share|improve this answer














          1. It's very surprising that your custom exception-class can throw an exception for anything but original creation. std::exception and derived standard classes aren't allowed to do that.


          2. Is it actually significant whether the object stores a stack-trace at all? Most likely not. So, consider simply modifying the passed message instead of creating your own classes. That calls for a (potentially templated) function instead.


          3. As-is, you store the original message, and then try to store the enhanced message and a flag that the enhanced message exists (which is equivalent to not being empty, so why a flag???) and should be used instead. That's a waste.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 1 hour ago

























          answered 1 hour ago









          Deduplicator

          10.4k1849




          10.4k1849











          • I'm sorry, but I don't think I understand the 1st point. Do you mean the lack of noexcept specifier alongside the constructors and assignment operator? If not, could you elaborate, please?
            – Jacajack
            1 hour ago






          • 1




            I mean that the copy- ctor/assignment can throw, as the std::string-member may need to allocate memory. But do you really want to upgrade it from throw std::bad_alloc; to std::terminate(), instead of going the COW-route?
            – Deduplicator
            46 mins ago










          • Alright, I see. I didn't think of that. As you said, the dedicated throw function seems like a much better solution now. Thanks for help.
            – Jacajack
            38 mins ago
















          • I'm sorry, but I don't think I understand the 1st point. Do you mean the lack of noexcept specifier alongside the constructors and assignment operator? If not, could you elaborate, please?
            – Jacajack
            1 hour ago






          • 1




            I mean that the copy- ctor/assignment can throw, as the std::string-member may need to allocate memory. But do you really want to upgrade it from throw std::bad_alloc; to std::terminate(), instead of going the COW-route?
            – Deduplicator
            46 mins ago










          • Alright, I see. I didn't think of that. As you said, the dedicated throw function seems like a much better solution now. Thanks for help.
            – Jacajack
            38 mins ago















          I'm sorry, but I don't think I understand the 1st point. Do you mean the lack of noexcept specifier alongside the constructors and assignment operator? If not, could you elaborate, please?
          – Jacajack
          1 hour ago




          I'm sorry, but I don't think I understand the 1st point. Do you mean the lack of noexcept specifier alongside the constructors and assignment operator? If not, could you elaborate, please?
          – Jacajack
          1 hour ago




          1




          1




          I mean that the copy- ctor/assignment can throw, as the std::string-member may need to allocate memory. But do you really want to upgrade it from throw std::bad_alloc; to std::terminate(), instead of going the COW-route?
          – Deduplicator
          46 mins ago




          I mean that the copy- ctor/assignment can throw, as the std::string-member may need to allocate memory. But do you really want to upgrade it from throw std::bad_alloc; to std::terminate(), instead of going the COW-route?
          – Deduplicator
          46 mins ago












          Alright, I see. I didn't think of that. As you said, the dedicated throw function seems like a much better solution now. Thanks for help.
          – Jacajack
          38 mins ago




          Alright, I see. I didn't think of that. As you said, the dedicated throw function seems like a much better solution now. Thanks for help.
          – Jacajack
          38 mins ago










          Jacajack is a new contributor. Be nice, and check out our Code of Conduct.









           

          draft saved


          draft discarded


















          Jacajack is a new contributor. Be nice, and check out our Code of Conduct.












          Jacajack is a new contributor. Be nice, and check out our Code of Conduct.











          Jacajack is a new contributor. Be nice, and check out our Code of Conduct.













           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f203823%2fcustom-c-exception-class-with-stack-trace-generation%23new-answer', 'question_page');

          );

          Post as a guest













































































          Comments

          Popular posts from this blog

          What does second last employer means? [closed]

          Installing NextGIS Connect into QGIS 3?

          One-line joke