// Copyright (c) 2012, Evgeny Panasyuk
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// e-mail: E?????[dot]P???????[at]gmail.???
namespace stack_unwinding
{
#if defined(_MSC_VER)
namespace details {extern "C" char * _getptd(); }
inline unsigned uncaught_exception_count()
{
// MSVC specific. Tested on {MSVC2005SP1,MSVC2008SP1,MSVC2010SP1,MSVC2012}x{x32,x64}.
return *(static_cast<unsigned*>(static_cast<void*>( details::_getptd() + (sizeof(void*)==8 ? 0x100 : 0x90) ))); // x32 offset - 0x90 , x64 - 0x100
}
#elif defined(__GNUG__) || defined(__CLANG__)
namespace details { extern "C" char * __cxa_get_globals(); }
inline unsigned uncaught_exception_count()
{
// Tested on {clang 3.2,GCC 3.5.6,,GCC 4.1.2,GCC 4.4.6,GCC 4.4.7}x{x32,x64}
return *(static_cast<unsigned*>(static_cast<void*>( details::__cxa_get_globals() + (sizeof(void*)==8 ? 0x8 : 0x4) ))); // x32 offset - 0x4 , x64 - 0x8
}
#endif
}
#include <iostream>
#include <ostream>
#include <string>
#include <vector>
#include <numeric>
#include <algorithm>
#include <functional>
using namespace std;
vector<unsigned> exception_counts;
const unsigned test_count=500;
struct ExpCountSaver
{
~ExpCountSaver()
{
unsigned exceptions_count=stack_unwinding::uncaught_exception_count();
cout << exceptions_count << endl;
exception_counts.push_back(exceptions_count);
}
};
template<int n>
struct ExptSwallower
{
~ExptSwallower()
{
try
{
ExpCountSaver p;
ExptSwallower<n-1> a;
throw 1;
(void)p;(void)a;
}catch(int){}
}
};
template<>
struct ExptSwallower<0>
{
~ExptSwallower() {}
};
int main(int,char *[])
{
exception_counts.reserve(test_count);
try
{
ExptSwallower<test_count> test;
} catch(int) {}
if(exception_counts.size()!=test_count)
return 1;
adjacent_difference(exception_counts.rbegin(),exception_counts.rend(),exception_counts.rbegin());
if
(
find_if(exception_counts.begin(),exception_counts.end(), bind2nd(not_equal_to<unsigned>(),1) )
!=
exception_counts.end()
)
return 2;
return 0;
}
Ly8gQ29weXJpZ2h0IChjKSAyMDEyLCBFdmdlbnkgUGFuYXN5dWsKIAovLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvciBvcmdhbml6YXRpb24KLy8gb2J0YWluaW5nIGEgY29weSBvZiB0aGUgc29mdHdhcmUgYW5kIGFjY29tcGFueWluZyBkb2N1bWVudGF0aW9uIGNvdmVyZWQgYnkKLy8gdGhpcyBsaWNlbnNlICh0aGUgIlNvZnR3YXJlIikgdG8gdXNlLCByZXByb2R1Y2UsIGRpc3BsYXksIGRpc3RyaWJ1dGUsCi8vIGV4ZWN1dGUsIGFuZCB0cmFuc21pdCB0aGUgU29mdHdhcmUsIGFuZCB0byBwcmVwYXJlIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlCi8vIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHRoaXJkLXBhcnRpZXMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvCi8vIGRvIHNvLCBhbGwgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nOgovLyAKLy8gVGhlIGNvcHlyaWdodCBub3RpY2VzIGluIHRoZSBTb2Z0d2FyZSBhbmQgdGhpcyBlbnRpcmUgc3RhdGVtZW50LCBpbmNsdWRpbmcKLy8gdGhlIGFib3ZlIGxpY2Vuc2UgZ3JhbnQsIHRoaXMgcmVzdHJpY3Rpb24gYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciwKLy8gbXVzdCBiZSBpbmNsdWRlZCBpbiBhbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgaW4gd2hvbGUgb3IgaW4gcGFydCwgYW5kCi8vIGFsbCBkZXJpdmF0aXZlIHdvcmtzIG9mIHRoZSBTb2Z0d2FyZSwgdW5sZXNzIHN1Y2ggY29waWVzIG9yIGRlcml2YXRpdmUKLy8gd29ya3MgYXJlIHNvbGVseSBpbiB0aGUgZm9ybSBvZiBtYWNoaW5lLWV4ZWN1dGFibGUgb2JqZWN0IGNvZGUgZ2VuZXJhdGVkIGJ5Ci8vIGEgc291cmNlIGxhbmd1YWdlIHByb2Nlc3Nvci4KLy8gCi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLAovLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSwgVElUTEUgQU5EIE5PTi1JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UCi8vIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSUyBPUiBBTllPTkUgRElTVFJJQlVUSU5HIFRIRSBTT0ZUV0FSRSBCRSBMSUFCTEUKLy8gRk9SIEFOWSBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsCi8vIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUgovLyBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuCiAKLy8gZS1tYWlsOiBFPz8/Pz9bZG90XVA/Pz8/Pz8/W2F0XWdtYWlsLj8/PwogCm5hbWVzcGFjZSBzdGFja191bndpbmRpbmcKewogCiNpZiBkZWZpbmVkKF9NU0NfVkVSKQpuYW1lc3BhY2UgZGV0YWlscyB7ZXh0ZXJuICJDIiBjaGFyICogX2dldHB0ZCgpOyB9CmlubGluZSB1bnNpZ25lZCB1bmNhdWdodF9leGNlcHRpb25fY291bnQoKQp7CiAgICAvLyBNU1ZDIHNwZWNpZmljLiBUZXN0ZWQgb24ge01TVkMyMDA1U1AxLE1TVkMyMDA4U1AxLE1TVkMyMDEwU1AxLE1TVkMyMDEyfXh7eDMyLHg2NH0uCiAgICByZXR1cm4gKihzdGF0aWNfY2FzdDx1bnNpZ25lZCo+KHN0YXRpY19jYXN0PHZvaWQqPiggZGV0YWlsczo6X2dldHB0ZCgpICsgKHNpemVvZih2b2lkKik9PTggPyAweDEwMCA6IDB4OTApICkpKTsgLy8geDMyIG9mZnNldCAtIDB4OTAgLCB4NjQgLSAweDEwMAp9CiNlbGlmIGRlZmluZWQoX19HTlVHX18pIHx8IGRlZmluZWQoX19DTEFOR19fKQpuYW1lc3BhY2UgZGV0YWlscyB7IGV4dGVybiAiQyIgY2hhciAqIF9fY3hhX2dldF9nbG9iYWxzKCk7IH0KaW5saW5lIHVuc2lnbmVkIHVuY2F1Z2h0X2V4Y2VwdGlvbl9jb3VudCgpCnsKICAgIC8vIFRlc3RlZCBvbiB7Y2xhbmcgMy4yLEdDQyAzLjUuNiwsR0NDIDQuMS4yLEdDQyA0LjQuNixHQ0MgNC40Ljd9eHt4MzIseDY0fQogICAgcmV0dXJuICooc3RhdGljX2Nhc3Q8dW5zaWduZWQqPihzdGF0aWNfY2FzdDx2b2lkKj4oIGRldGFpbHM6Ol9fY3hhX2dldF9nbG9iYWxzKCkgKyAoc2l6ZW9mKHZvaWQqKT09OCA/IDB4OCA6IDB4NCkgKSkpOyAvLyB4MzIgb2Zmc2V0IC0gMHg0ICwgeDY0IC0gMHg4Cn0KI2VuZGlmCn0KIAojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8bnVtZXJpYz4KI2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiAKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKIAp2ZWN0b3I8dW5zaWduZWQ+IGV4Y2VwdGlvbl9jb3VudHM7CmNvbnN0IHVuc2lnbmVkIHRlc3RfY291bnQ9NTAwOwogCnN0cnVjdCBFeHBDb3VudFNhdmVyCnsKICAgIH5FeHBDb3VudFNhdmVyKCkKICAgIHsKICAgICAgICB1bnNpZ25lZCBleGNlcHRpb25zX2NvdW50PXN0YWNrX3Vud2luZGluZzo6dW5jYXVnaHRfZXhjZXB0aW9uX2NvdW50KCk7CiAgICAgICAgY291dCA8PCBleGNlcHRpb25zX2NvdW50IDw8IGVuZGw7CiAgICAgICAgZXhjZXB0aW9uX2NvdW50cy5wdXNoX2JhY2soZXhjZXB0aW9uc19jb3VudCk7CiAgICB9Cn07CiAKIAp0ZW1wbGF0ZTxpbnQgbj4Kc3RydWN0IEV4cHRTd2FsbG93ZXIKewogICAgfkV4cHRTd2FsbG93ZXIoKQogICAgewogICAgICAgIHRyeQogICAgICAgIHsKICAgICAgICAgICAgRXhwQ291bnRTYXZlciBwOwogICAgICAgICAgICBFeHB0U3dhbGxvd2VyPG4tMT4gYTsKICAgICAgICAgICAgdGhyb3cgMTsKICAgICAgICAgICAgKHZvaWQpcDsodm9pZClhOwogICAgICAgIH1jYXRjaChpbnQpe30KICAgIH0KfTsKdGVtcGxhdGU8PgpzdHJ1Y3QgRXhwdFN3YWxsb3dlcjwwPgp7CiAgICB+RXhwdFN3YWxsb3dlcigpIHt9Cn07CmludCBtYWluKGludCxjaGFyICpbXSkKewogICAgZXhjZXB0aW9uX2NvdW50cy5yZXNlcnZlKHRlc3RfY291bnQpOwogICAgdHJ5CiAgICB7CiAgICAgICAgRXhwdFN3YWxsb3dlcjx0ZXN0X2NvdW50PiB0ZXN0OwogICAgfSBjYXRjaChpbnQpIHt9CiAgICBpZihleGNlcHRpb25fY291bnRzLnNpemUoKSE9dGVzdF9jb3VudCkKICAgICAgICByZXR1cm4gMTsKICAgIGFkamFjZW50X2RpZmZlcmVuY2UoZXhjZXB0aW9uX2NvdW50cy5yYmVnaW4oKSxleGNlcHRpb25fY291bnRzLnJlbmQoKSxleGNlcHRpb25fY291bnRzLnJiZWdpbigpKTsKICAgIGlmCiAgICAoCiAgICAgICAgZmluZF9pZihleGNlcHRpb25fY291bnRzLmJlZ2luKCksZXhjZXB0aW9uX2NvdW50cy5lbmQoKSwgYmluZDJuZChub3RfZXF1YWxfdG88dW5zaWduZWQ+KCksMSkgKQogICAgICAgICAgICAhPQogICAgICAgIGV4Y2VwdGlvbl9jb3VudHMuZW5kKCkKICAgICkKICAgICAgICByZXR1cm4gMjsKICAgIHJldHVybiAwOwp9Cg==