ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

297 lines
7.8 KiB

  1. //
  2. // Copyright (C) 2009-2012 Artyom Beilis (Tonkikh)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. #ifndef BOOSTER_BACKTRACE_H
  9. #define BOOSTER_BACKTRACE_H
  10. #include <booster/config.h>
  11. #include <stdexcept>
  12. #include <typeinfo>
  13. #include <string>
  14. #include <vector>
  15. #include <iosfwd>
  16. namespace booster {
  17. ///
  18. /// \brief Namespace that holds basic operations
  19. /// for implementing stack trace
  20. ///
  21. namespace stack_trace {
  22. ///
  23. /// \brief Record stack frame
  24. ///
  25. /// Records at most \a size stack frames returning the pointers to the running
  26. /// code into \a addresses vector that should have at least size places
  27. ///
  28. /// returns that number of actually recorded frames
  29. ///
  30. BOOSTER_API int trace(void **addresses,int size);
  31. ///
  32. /// \brief Print stack trace
  33. ///
  34. /// Writes stack trace recorded \ref trace function of \a size size to the output stream
  35. ///
  36. BOOSTER_API void write_symbols(void *const *addresses,int size,std::ostream &);
  37. ///
  38. /// \brief Get stack trace information about a single address recorded
  39. ///
  40. BOOSTER_API std::string get_symbol(void *address);
  41. ///
  42. /// \brief Get stack trace information about multiple address recorded
  43. ///
  44. BOOSTER_API std::string get_symbols(void * const *address,int size);
  45. } // stack_trace
  46. ///
  47. /// \brief the class that records the stack trace when it is created,
  48. ///
  49. /// It is a base class for all exceptions that record stack trace
  50. ///
  51. class backtrace {
  52. public:
  53. ///
  54. /// The default number of recorded frames
  55. ///
  56. static size_t const default_stack_size = 32;
  57. ///
  58. /// Create stack trace recording at most \a frames_no stack frames
  59. ///
  60. backtrace(size_t frames_no = default_stack_size)
  61. {
  62. if(frames_no == 0)
  63. return;
  64. frames_.resize(frames_no,0);
  65. int size = stack_trace::trace(&frames_.front(),frames_no);
  66. frames_.resize(size);
  67. }
  68. virtual ~backtrace() throw()
  69. {
  70. }
  71. ///
  72. /// Get the actual number of recorded stack frames
  73. ///
  74. size_t stack_size() const
  75. {
  76. return frames_.size();
  77. }
  78. ///
  79. /// Get the returned address for the stack frame number \a frame_no
  80. ///
  81. void *return_address(unsigned frame_no) const
  82. {
  83. if(frame_no < stack_size())
  84. return frames_[frame_no];
  85. return 0;
  86. }
  87. ///
  88. /// Print the stack trace frame for the frame \a frame_no to the stream \a out
  89. ///
  90. void trace_line(unsigned frame_no,std::ostream &out) const
  91. {
  92. if(frame_no < frames_.size())
  93. stack_trace::write_symbols(&frames_[frame_no],1,out);
  94. }
  95. ///
  96. /// Get a readable stack trace frame for the frame \a frame_no
  97. ///
  98. std::string trace_line(unsigned frame_no) const
  99. {
  100. if(frame_no < frames_.size())
  101. return stack_trace::get_symbol(frames_[frame_no]);
  102. return std::string();
  103. }
  104. ///
  105. /// Get full stack trace as a string
  106. ///
  107. std::string trace() const
  108. {
  109. if(frames_.empty())
  110. return std::string();
  111. return stack_trace::get_symbols(&frames_.front(),frames_.size());
  112. }
  113. ///
  114. /// Print full stack trace to a stream \a out
  115. ///
  116. void trace(std::ostream &out) const
  117. {
  118. if(frames_.empty())
  119. return;
  120. stack_trace::write_symbols(&frames_.front(),frames_.size(),out);
  121. }
  122. private:
  123. std::vector<void *> frames_;
  124. };
  125. ///
  126. /// \brief Same as std::exception but records stack trace
  127. ///
  128. class exception : public std::exception, public backtrace {
  129. public:
  130. };
  131. ///
  132. /// \brief Same as std::bad_cast but records stack trace
  133. ///
  134. class bad_cast : public std::bad_cast, public backtrace {
  135. public:
  136. };
  137. ///
  138. /// \brief Same as std::runtime_error but records stack trace
  139. ///
  140. class runtime_error: public std::runtime_error, public backtrace {
  141. public:
  142. explicit runtime_error(std::string const &s) : std::runtime_error(s)
  143. {
  144. }
  145. };
  146. ///
  147. /// \brief Same as std::range_error but records stack trace
  148. ///
  149. class range_error: public std::range_error, public backtrace {
  150. public:
  151. explicit range_error(std::string const &s) : std::range_error(s)
  152. {
  153. }
  154. };
  155. ///
  156. /// \brief Same as std::overflow_error but records stack trace
  157. ///
  158. class overflow_error: public std::overflow_error, public backtrace {
  159. public:
  160. explicit overflow_error(std::string const &s) : std::overflow_error(s)
  161. {
  162. }
  163. };
  164. ///
  165. /// \brief Same as std::underflow_error but records stack trace
  166. ///
  167. class underflow_error: public std::underflow_error, public backtrace {
  168. public:
  169. explicit underflow_error(std::string const &s) : std::underflow_error(s)
  170. {
  171. }
  172. };
  173. ///
  174. /// \brief Same as std::logic_error but records stack trace
  175. ///
  176. class logic_error: public std::logic_error, public backtrace {
  177. public:
  178. explicit logic_error(std::string const &s) : std::logic_error(s)
  179. {
  180. }
  181. };
  182. ///
  183. /// \brief Same as std::domain_error but records stack trace
  184. ///
  185. class domain_error: public std::domain_error, public backtrace {
  186. public:
  187. explicit domain_error(std::string const &s) : std::domain_error(s)
  188. {
  189. }
  190. };
  191. ///
  192. /// \brief Same as std::length_error but records stack trace
  193. ///
  194. class length_error: public std::length_error, public backtrace {
  195. public:
  196. explicit length_error(std::string const &s) : std::length_error(s)
  197. {
  198. }
  199. };
  200. ///
  201. /// \brief Same as std::invalid_argument but records stack trace
  202. ///
  203. class invalid_argument : public std::invalid_argument, public backtrace {
  204. public:
  205. explicit invalid_argument(std::string const &s) : std::invalid_argument(s)
  206. {
  207. }
  208. };
  209. ///
  210. /// \brief Same as std::out_of_range but records stack trace
  211. ///
  212. class out_of_range : public std::out_of_range, public backtrace {
  213. public:
  214. explicit out_of_range(std::string const &s) : std::out_of_range(s)
  215. {
  216. }
  217. };
  218. /// \cond INTERNAL
  219. namespace details {
  220. class trace_manip {
  221. public:
  222. trace_manip(backtrace const *tr) :
  223. tr_(tr)
  224. {
  225. }
  226. std::ostream &write(std::ostream &out) const
  227. {
  228. if(tr_)
  229. tr_->trace(out);
  230. return out;
  231. }
  232. private:
  233. backtrace const *tr_;
  234. };
  235. inline std::ostream &operator<<(std::ostream &out,details::trace_manip const &t)
  236. {
  237. return t.write(out);
  238. }
  239. }
  240. /// \endcond
  241. ///
  242. /// \brief manipulator that print stack trace for the exception \a e if it is derived from backtrace.
  243. ///
  244. /// For example:
  245. ///
  246. /// \code
  247. ///
  248. /// catch(std::exception const &e) {
  249. /// std::cerr << e.what() << std::endl;
  250. /// std::cerr << booster::trace(e);
  251. /// }
  252. ///
  253. /// \endcode
  254. ///
  255. template<typename E>
  256. details::trace_manip trace(E const &e)
  257. {
  258. backtrace const *tr = dynamic_cast<backtrace const *>(&e);
  259. return details::trace_manip(tr);
  260. }
  261. } // booster
  262. #endif
  263. // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4