fork download
  1. // Copyright (c) 2012, Evgeny Panasyuk
  2.  
  3. // Permission is hereby granted, free of charge, to any person or organization
  4. // obtaining a copy of the software and accompanying documentation covered by
  5. // this license (the "Software") to use, reproduce, display, distribute,
  6. // execute, and transmit the Software, and to prepare derivative works of the
  7. // Software, and to permit third-parties to whom the Software is furnished to
  8. // do so, all subject to the following:
  9. //
  10. // The copyright notices in the Software and this entire statement, including
  11. // the above license grant, this restriction and the following disclaimer,
  12. // must be included in all copies of the Software, in whole or in part, and
  13. // all derivative works of the Software, unless such copies or derivative
  14. // works are solely in the form of machine-executable object code generated by
  15. // a source language processor.
  16. //
  17. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
  20. // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
  21. // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
  22. // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. // DEALINGS IN THE SOFTWARE.
  24.  
  25. // e-mail: E?????[dot]P???????[at]gmail.???
  26.  
  27. namespace stack_unwinding
  28. {
  29.  
  30. #if defined(_MSC_VER)
  31. namespace details {extern "C" char * _getptd(); }
  32. inline unsigned uncaught_exception_count()
  33. {
  34. // MSVC specific. Tested on {MSVC2005SP1,MSVC2008SP1,MSVC2010SP1,MSVC2012}x{x32,x64}.
  35. return *(static_cast<unsigned*>(static_cast<void*>( details::_getptd() + (sizeof(void*)==8 ? 0x100 : 0x90) ))); // x32 offset - 0x90 , x64 - 0x100
  36. }
  37. #elif defined(__GNUG__) || defined(__CLANG__)
  38. namespace details { extern "C" char * __cxa_get_globals(); }
  39. inline unsigned uncaught_exception_count()
  40. {
  41. // Tested on {clang 3.2,GCC 3.5.6,,GCC 4.1.2,GCC 4.4.6,GCC 4.4.7}x{x32,x64}
  42. return *(static_cast<unsigned*>(static_cast<void*>( details::__cxa_get_globals() + (sizeof(void*)==8 ? 0x8 : 0x4) ))); // x32 offset - 0x4 , x64 - 0x8
  43. }
  44. #endif
  45. }
  46.  
  47. #include <iostream>
  48. #include <ostream>
  49. #include <string>
  50. #include <vector>
  51. #include <numeric>
  52. #include <algorithm>
  53. #include <functional>
  54.  
  55. using namespace std;
  56.  
  57. vector<unsigned> exception_counts;
  58. const unsigned test_count=500;
  59.  
  60. struct ExpCountSaver
  61. {
  62. ~ExpCountSaver()
  63. {
  64. exception_counts.push_back(stack_unwinding::uncaught_exception_count());
  65. }
  66. };
  67.  
  68.  
  69. template<int n>
  70. struct ExptSwallower
  71. {
  72. ~ExptSwallower()
  73. {
  74. try
  75. {
  76. ExpCountSaver p;
  77. ExptSwallower<n-1> a;
  78. throw 1;
  79. (void)p;(void)a;
  80. }catch(int){}
  81. }
  82. };
  83. template<>
  84. struct ExptSwallower<0>
  85. {
  86. ~ExptSwallower() {}
  87. };
  88. int main(int,char *[])
  89. {
  90. exception_counts.reserve(test_count);
  91. try
  92. {
  93. ExptSwallower<test_count>();
  94. } catch(int) {}
  95. if(exception_counts.size()!=test_count)
  96. return 1;
  97. adjacent_difference(exception_counts.rbegin(),exception_counts.rend(),exception_counts.rbegin());
  98. if
  99. (
  100. find_if(exception_counts.begin(),exception_counts.end(), bind2nd(not_equal_to<unsigned>(),1) )
  101. !=
  102. exception_counts.end()
  103. )
  104. return 2;
  105. return 0;
  106. }
  107.  
Success #stdin #stdout 0.02s 2912KB
stdin
Standard input is empty
stdout
Standard output is empty