// 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()
{
exception_counts.push_back(stack_unwinding::uncaught_exception_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>();
} 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;
}
Ly8gQ29weXJpZ2h0IChjKSAyMDEyLCBFdmdlbnkgUGFuYXN5dWsKCi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9yIG9yZ2FuaXphdGlvbgovLyBvYnRhaW5pbmcgYSBjb3B5IG9mIHRoZSBzb2Z0d2FyZSBhbmQgYWNjb21wYW55aW5nIGRvY3VtZW50YXRpb24gY292ZXJlZCBieQovLyB0aGlzIGxpY2Vuc2UgKHRoZSAiU29mdHdhcmUiKSB0byB1c2UsIHJlcHJvZHVjZSwgZGlzcGxheSwgZGlzdHJpYnV0ZSwKLy8gZXhlY3V0ZSwgYW5kIHRyYW5zbWl0IHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHByZXBhcmUgZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUKLy8gU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgdGhpcmQtcGFydGllcyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8KLy8gZG8gc28sIGFsbCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmc6Ci8vIAovLyBUaGUgY29weXJpZ2h0IG5vdGljZXMgaW4gdGhlIFNvZnR3YXJlIGFuZCB0aGlzIGVudGlyZSBzdGF0ZW1lbnQsIGluY2x1ZGluZwovLyB0aGUgYWJvdmUgbGljZW5zZSBncmFudCwgdGhpcyByZXN0cmljdGlvbiBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLAovLyBtdXN0IGJlIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBpbiB3aG9sZSBvciBpbiBwYXJ0LCBhbmQKLy8gYWxsIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNvZnR3YXJlLCB1bmxlc3Mgc3VjaCBjb3BpZXMgb3IgZGVyaXZhdGl2ZQovLyB3b3JrcyBhcmUgc29sZWx5IGluIHRoZSBmb3JtIG9mIG1hY2hpbmUtZXhlY3V0YWJsZSBvYmplY3QgY29kZSBnZW5lcmF0ZWQgYnkKLy8gYSBzb3VyY2UgbGFuZ3VhZ2UgcHJvY2Vzc29yLgovLyAKLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1IKLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksCi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLCBUSVRMRSBBTkQgTk9OLUlORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQKLy8gU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVJTIE9SIEFOWU9ORSBESVNUUklCVVRJTkcgVEhFIFNPRlRXQVJFIEJFIExJQUJMRQovLyBGT1IgQU5ZIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwKLy8gQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSCi8vIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS4KCi8vIGUtbWFpbDogRT8/Pz8/W2RvdF1QPz8/Pz8/P1thdF1nbWFpbC4/Pz8KCm5hbWVzcGFjZSBzdGFja191bndpbmRpbmcKewoKI2lmIGRlZmluZWQoX01TQ19WRVIpCm5hbWVzcGFjZSBkZXRhaWxzIHtleHRlcm4gIkMiIGNoYXIgKiBfZ2V0cHRkKCk7IH0KaW5saW5lIHVuc2lnbmVkIHVuY2F1Z2h0X2V4Y2VwdGlvbl9jb3VudCgpCnsKICAgIC8vIE1TVkMgc3BlY2lmaWMuIFRlc3RlZCBvbiB7TVNWQzIwMDVTUDEsTVNWQzIwMDhTUDEsTVNWQzIwMTBTUDEsTVNWQzIwMTJ9eHt4MzIseDY0fS4KICAgIHJldHVybiAqKHN0YXRpY19jYXN0PHVuc2lnbmVkKj4oc3RhdGljX2Nhc3Q8dm9pZCo+KCBkZXRhaWxzOjpfZ2V0cHRkKCkgKyAoc2l6ZW9mKHZvaWQqKT09OCA/IDB4MTAwIDogMHg5MCkgKSkpOyAvLyB4MzIgb2Zmc2V0IC0gMHg5MCAsIHg2NCAtIDB4MTAwCn0KI2VsaWYgZGVmaW5lZChfX0dOVUdfXykgfHwgZGVmaW5lZChfX0NMQU5HX18pCm5hbWVzcGFjZSBkZXRhaWxzIHsgZXh0ZXJuICJDIiBjaGFyICogX19jeGFfZ2V0X2dsb2JhbHMoKTsgfQppbmxpbmUgdW5zaWduZWQgdW5jYXVnaHRfZXhjZXB0aW9uX2NvdW50KCkKewogICAgLy8gVGVzdGVkIG9uIHtjbGFuZyAzLjIsR0NDIDMuNS42LCxHQ0MgNC4xLjIsR0NDIDQuNC42LEdDQyA0LjQuN314e3gzMix4NjR9CiAgICByZXR1cm4gKihzdGF0aWNfY2FzdDx1bnNpZ25lZCo+KHN0YXRpY19jYXN0PHZvaWQqPiggZGV0YWlsczo6X19jeGFfZ2V0X2dsb2JhbHMoKSArIChzaXplb2Yodm9pZCopPT04ID8gMHg4IDogMHg0KSApKSk7IC8vIHgzMiBvZmZzZXQgLSAweDQgLCB4NjQgLSAweDgKfQojZW5kaWYKfQoKI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8b3N0cmVhbT4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPG51bWVyaWM+CiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDxmdW5jdGlvbmFsPgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnZlY3Rvcjx1bnNpZ25lZD4gZXhjZXB0aW9uX2NvdW50czsKY29uc3QgdW5zaWduZWQgdGVzdF9jb3VudD01MDA7CgpzdHJ1Y3QgRXhwQ291bnRTYXZlcgp7CiAgICB+RXhwQ291bnRTYXZlcigpCiAgICB7CiAgICAgICAgZXhjZXB0aW9uX2NvdW50cy5wdXNoX2JhY2soc3RhY2tfdW53aW5kaW5nOjp1bmNhdWdodF9leGNlcHRpb25fY291bnQoKSk7CiAgICB9Cn07CgoKdGVtcGxhdGU8aW50IG4+CnN0cnVjdCBFeHB0U3dhbGxvd2VyCnsKICAgIH5FeHB0U3dhbGxvd2VyKCkKICAgIHsKICAgICAgICB0cnkKICAgICAgICB7CiAgICAgICAgICAgIEV4cENvdW50U2F2ZXIgcDsKICAgICAgICAgICAgRXhwdFN3YWxsb3dlcjxuLTE+IGE7CiAgICAgICAgICAgIHRocm93IDE7CiAgICAgICAgICAgICh2b2lkKXA7KHZvaWQpYTsKICAgICAgICB9Y2F0Y2goaW50KXt9CiAgICB9Cn07CnRlbXBsYXRlPD4Kc3RydWN0IEV4cHRTd2FsbG93ZXI8MD4KewogICAgfkV4cHRTd2FsbG93ZXIoKSB7fQp9OwppbnQgbWFpbihpbnQsY2hhciAqW10pCnsKICAgIGV4Y2VwdGlvbl9jb3VudHMucmVzZXJ2ZSh0ZXN0X2NvdW50KTsKICAgIHRyeQogICAgewogICAgICAgIEV4cHRTd2FsbG93ZXI8dGVzdF9jb3VudD4oKTsKICAgIH0gY2F0Y2goaW50KSB7fQogICAgaWYoZXhjZXB0aW9uX2NvdW50cy5zaXplKCkhPXRlc3RfY291bnQpCiAgICAgICAgcmV0dXJuIDE7CiAgICBhZGphY2VudF9kaWZmZXJlbmNlKGV4Y2VwdGlvbl9jb3VudHMucmJlZ2luKCksZXhjZXB0aW9uX2NvdW50cy5yZW5kKCksZXhjZXB0aW9uX2NvdW50cy5yYmVnaW4oKSk7CiAgICBpZgogICAgKAogICAgICAgIGZpbmRfaWYoZXhjZXB0aW9uX2NvdW50cy5iZWdpbigpLGV4Y2VwdGlvbl9jb3VudHMuZW5kKCksIGJpbmQybmQobm90X2VxdWFsX3RvPHVuc2lnbmVkPigpLDEpICkKICAgICAgICAgICAgIT0KICAgICAgICBleGNlcHRpb25fY291bnRzLmVuZCgpCiAgICApCiAgICAgICAgcmV0dXJuIDI7CiAgICByZXR1cm4gMDsKfQo=