fork(1) download
  1.  
  2. #include <iostream>
  3. #include <cassert>
  4.  
  5. class stackelement {
  6. stackelement* caller;
  7. stackelement* callee;
  8. static stackelement*& frameptr()
  9. {
  10. static stackelement* frameptr=NULL;
  11. return frameptr;
  12. }
  13. protected:
  14. virtual const char* get_name() const =0;
  15. virtual void printparams(std::ostream& out,
  16. const char* before_params,
  17. const char* between_params,
  18. const char* after_params) const =0;
  19. public:
  20. stackelement()
  21. : caller(frameptr()), callee(NULL)
  22. { frameptr() = this;}
  23. stackelement(const stackelement& r)
  24. : caller(r.caller), callee(r.callee)
  25. {
  26. assert(frameptr() == &r);
  27. frameptr() = this;
  28. }
  29. stackelement& operator=(const stackelement& r) {
  30. assert(frameptr() == &r);
  31. caller = r.caller;
  32. callee = r.callee;
  33. frameptr() = this;
  34. return *this;
  35. }
  36. virtual ~stackelement() {
  37. if (caller)
  38. caller->callee = NULL;
  39. frameptr() = caller;
  40. }
  41. static void print(std::ostream& out,
  42. const char* begin_line="",
  43. const char* before_params=" with ",
  44. const char* between_params=", ",
  45. const char* after_params=".",
  46. const char* end_line="\n") {
  47. stackelement* self = frameptr();
  48. do {
  49. out << begin_line << self->get_name();
  50. self->printparams(out, before_params, between_params, after_params);
  51. out << end_line;
  52. self = self->caller;
  53. } while(self);
  54. }
  55. };
  56.  
  57. template<class P0, class P1, class P2, class P3, class P4>
  58. struct stackinstance : stackelement {
  59. protected:
  60. const char* name;
  61. P0& p0;
  62. P1& p1;
  63. P2& p2;
  64. P3& p3;
  65. P4& p4;
  66. public:
  67. template<int N>
  68. stackinstance(const char(&name_)[N], P0& p0_, P1& p1_, P2& p2_, P3& p3_, P4& p4_)
  69. :name(name_), p0(p0_), p1(p1_), p2(p2_), p3(p3_), p4(p4_) {}
  70. protected:
  71. virtual const char* get_name() const {return name;}
  72. virtual void printparams(std::ostream& out,
  73. const char* before_params,
  74. const char* between_params,
  75. const char* after_params) const
  76. {out << before_params << p0
  77. << between_params << p1
  78. << between_params << p2
  79. << between_params << p3
  80. << between_params << p4
  81. << after_params; }
  82. };
  83.  
  84. template<class P0, class P1, class P2, class P3>
  85. struct stackinstance<P0, P1, P2, P3, void> : stackelement {
  86. protected:
  87. const char* name;
  88. P0& p0;
  89. P1& p1;
  90. P2& p2;
  91. P3& p3;
  92. public:
  93. template<int N>
  94. stackinstance(const char(&name_)[N], P0& p0_, P1& p1_, P2& p2_, P3& p3_)
  95. :name(name_), p0(p0_), p1(p1_), p2(p2_), p3(p3_) {}
  96. protected:
  97. virtual const char* get_name() const {return name;}
  98. virtual void printparams(std::ostream& out,
  99. const char* before_params,
  100. const char* between_params,
  101. const char* after_params) const
  102. {out << before_params << p0
  103. << between_params << p1
  104. << between_params << p2
  105. << between_params << p3
  106. << after_params; }
  107. };
  108.  
  109. template<class P0, class P1, class P2>
  110. struct stackinstance<P0, P1, P2, void, void> : stackelement {
  111. protected:
  112. const char* name;
  113. P0& p0;
  114. P1& p1;
  115. P2& p2;
  116. public:
  117. template<int N>
  118. stackinstance(const char(&name_)[N], P0& p0_, P1& p1_, P2& p2_)
  119. :name(name_), p0(p0_), p1(p1_), p2(p2_) {}
  120. protected:
  121. virtual const char* get_name() const {return name;}
  122. virtual void printparams(std::ostream& out,
  123. const char* before_params,
  124. const char* between_params,
  125. const char* after_params) const
  126. {out << before_params << p0
  127. << between_params << p1
  128. << between_params << p2
  129. << after_params; }
  130. };
  131.  
  132. template<class P0, class P1>
  133. struct stackinstance<P0, P1, void, void, void> : stackelement {
  134. protected:
  135. const char* name;
  136. P0& p0;
  137. P1& p1;
  138. public:
  139. template<int N>
  140. stackinstance(const char(&name_)[N], P0& p0_, P1& p1_)
  141. :name(name_), p0(p0_), p1(p1_) {}
  142. protected:
  143. virtual const char* get_name() const {return name;}
  144. virtual void printparams(std::ostream& out,
  145. const char* before_params,
  146. const char* between_params,
  147. const char* after_params) const
  148. {out << before_params << p0
  149. << between_params << p1
  150. << after_params; }
  151. };
  152.  
  153. template<class P0>
  154. struct stackinstance<P0, void, void, void, void> : stackelement {
  155. protected:
  156. const char* name;
  157. P0& p0;
  158. public:
  159. template<int N>
  160. stackinstance(const char(&name_)[N], P0& p0_)
  161. :name(name_), p0(p0_) {}
  162. protected:
  163. virtual const char* get_name() const {return name;}
  164. virtual void printparams(std::ostream& out,
  165. const char* before_params,
  166. const char* between_params,
  167. const char* after_params) const
  168. {out << before_params << p0
  169. << after_params; }
  170. };
  171.  
  172. template<>
  173. struct stackinstance<void, void, void, void, void> : stackelement {
  174. protected:
  175. const char* name;
  176. public:
  177. template<int N>
  178. stackinstance(const char(&name_)[N])
  179. :name(name_) {}
  180. protected:
  181. virtual const char* get_name() const {return name;}
  182. virtual void printparams(std::ostream&,
  183. const char*,
  184. const char*,
  185. const char*) const
  186. {}
  187. };
  188.  
  189. template<int N, class P0, class P1, class P2, class P3, class P4>
  190. stackinstance<P0, P1, P2, P3, P4> StackTrace(const char(&name_)[N], P0& p0_, P1& p1_, P2& p2_, P3& p3_, P4& p4_)
  191. {return stackinstance<P0, P1, P2, P3, P4>(name_, p0_, p1_, p2_, p3_, p4_);}
  192.  
  193. template<int N, class P0, class P1, class P2, class P3>
  194. stackinstance<P0, P1, P2, P3, void> StackTrace(const char(&name_)[N], P0& p0_, P1& p1_, P2& p2_, P3& p3_)
  195. {return stackinstance<P0, P1, P2, P3, void>(name_, p0_, p1_, p2_, p3_);}
  196.  
  197. template<int N, class P0, class P1, class P2>
  198. stackinstance<P0, P1, P2, void, void> StackTrace(const char(&name_)[N], P0& p0_, P1& p1_, P2& p2_)
  199. {return stackinstance<P0, P1, P2, void, void>(name_, p0_, p1_, p2_);}
  200.  
  201. template<int N, class P0, class P1>
  202. stackinstance<P0, P1, void, void, void> StackTrace(const char(&name_)[N], P0& p0_, P1& p1_)
  203. {return stackinstance<P0, P1, void, void, void>(name_, p0_, p1_);}
  204.  
  205. template<int N, class P0>
  206. stackinstance<P0, void, void, void, void> StackTrace(const char(&name_)[N], P0& p0_)
  207. {return stackinstance<P0, void, void, void, void>(name_, p0_);}
  208.  
  209. template<int N>
  210. stackinstance<void, void, void, void, void> StackTrace(const char(&name_)[N])
  211. {return stackinstance<void, void, void, void, void>(name_);}
  212.  
  213. #ifdef __GNUC__
  214. #define __FUNCSIG__ __PRETTY_FUNCTION__
  215. #endif
  216.  
  217.  
  218.  
  219.  
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226.  
  227.  
  228.  
  229. #include <iostream>
  230. #include <sstream>
  231. #include <exception>
  232. #include <stdexcept>
  233.  
  234. class stack_aware_exception : public std::runtime_error {
  235. std::string get_stack() {
  236. std::stringstream stacktrace;
  237. stackelement::print(stacktrace);
  238. return stacktrace.str();
  239. }
  240. public:
  241. stack_aware_exception() :std::runtime_error(get_stack()) {}
  242. };
  243.  
  244. unsigned thing(unsigned i) {
  245. auto trace = StackTrace(__FUNCSIG__, i);
  246. if (i==10)
  247. throw stack_aware_exception();
  248. else if (i==0)
  249. return i;
  250. return thing(i-1);
  251. }
  252.  
  253. int Foo() {
  254. auto trace = StackTrace(__FUNCSIG__);
  255. return thing(7) + thing(0) + thing(17);
  256. }
  257.  
  258. int main(int argc, char** argv) {
  259. auto trace = StackTrace(__FUNCSIG__, argc, argv);
  260. try {
  261. Foo();
  262. } catch(const stack_aware_exception& exc) {
  263. std::cout << exc.what();
  264. }
  265. return 0;
  266. }
Success #stdin #stdout 0s 2968KB
stdin
Standard input is empty
stdout
unsigned int thing(unsigned int) with 10.
unsigned int thing(unsigned int) with 11.
unsigned int thing(unsigned int) with 12.
unsigned int thing(unsigned int) with 13.
unsigned int thing(unsigned int) with 14.
unsigned int thing(unsigned int) with 15.
unsigned int thing(unsigned int) with 16.
unsigned int thing(unsigned int) with 17.
int Foo()
int main(int, char**) with 1, 0xbfde7164.