|
|
#include <stdio.h>
#include <windows.h>
#include <eh.h>
extern "C" ULONG DbgPrint ( PCH Format, ... );
extern "C" VOID DbgBreakPoint ( VOID );
#define FALSE 0
#define TRUE 1
#define NO_CTOR_THROW 1
#define NO_DTOR_THROW 2
#define B0 B b0(__FUNCTION__, __LINE__)
#define B1 B b1(__FUNCTION__, __LINE__)
#define B2 B b2(__FUNCTION__, __LINE__)
#define B3 B b3(__FUNCTION__, __LINE__)
#define B4 B b4(__FUNCTION__, __LINE__)
#define B5 B b5(__FUNCTION__, __LINE__)
#define B6 B b6(__FUNCTION__, __LINE__)
#define B7 B b7(__FUNCTION__, __LINE__)
#define B8 B b8(__FUNCTION__, __LINE__)
#define A0 A a0(__FUNCTION__, __LINE__)
#define A1 A a1(__FUNCTION__, __LINE__)
#define A2 A a2(__FUNCTION__, __LINE__)
#define A3 A a3(__FUNCTION__, __LINE__)
#define A4 A a4(__FUNCTION__, __LINE__)
#define A5 A a5(__FUNCTION__, __LINE__)
#define A6 A a6(__FUNCTION__, __LINE__)
#define A7 A a7(__FUNCTION__, __LINE__)
#define A8 A a8(__FUNCTION__, __LINE__)
const unsigned int NumMaxA = 100, NumMaxB = 100, NumTests = 9; int AObject[NumMaxA]; int BObject[NumMaxB]; int MaxTest = 10; int MaxObjectCount = 1; int Fail; int A_id; int B_id; typedef enum ClassName{clA = 'A', clB};
/*********************************** Class C *********************************/ class C { protected: const char *FuncName; unsigned int LineNumber; int id; ClassName CName;
void C::PrintCtor() { DbgPrint("%c ctor. id = %4d\t ", CName, id); if (FuncName) { DbgPrint("\tFunction = %s\tLineNum = %4d\n", FuncName, LineNumber); } else { DbgPrint("\n"); } fflush(stdout); } void C::PrintCtor(int n) { DbgPrint("%c cctor. id = %4d\tpid = %4d\t", CName, id, n); if (FuncName) { DbgPrint("\tFunction = %s\tLineNum = %4d\n", FuncName, LineNumber); } else { DbgPrint("\n"); } fflush(stdout); } void C::PrintDtor() { DbgPrint("%c dtor. id = %4d\t ", CName, id); if (FuncName) { DbgPrint("\tFunction = %s\tLineNum = %4d\n", FuncName, LineNumber); } else { DbgPrint("\n"); } fflush(stdout); }
void Alloc() { int *Arr = NULL; if (CName == clB) Arr = BObject; else if(CName == clA) Arr = AObject; else DbgPrint("ERROR: Alloc Unknown ClassName %c\n", CName); if (Arr) { if (Arr[id]) { DbgPrint("Error: id#%4d for %c already exists\n", id, CName); } Arr[id] = 1; } } void DAlloc() { int *Arr = NULL; if (CName == clB) Arr = BObject; else if(CName == clA) Arr = AObject; else DbgPrint("ERROR: Alloc Unknown ClassName %c\n", CName); if (Arr) { if (Arr[id] != 1) { DbgPrint("Error: id#%4d for %c already destructed\n", id, CName); } Arr[id]--; } } public: void print(){ DbgPrint("%c print. id = %4d\t ", CName, id); if (FuncName) { DbgPrint("\tFunction = %s\tLineNum = %4d\n", FuncName, LineNumber); } else { DbgPrint("\n"); } } C():id(0), CName(clA), FuncName(NULL), LineNumber(0){} ~C() { PrintDtor(); DAlloc(); } };
/*********************************** Class B *********************************/ class B : public C { public: B(); B(const B &b); B(const char *, unsigned int); };
B::B() { id = B_id++; CName = clB; PrintCtor(); Alloc(); }
B::B(const B &b) { id = B_id++; CName = clB; PrintCtor(b.id); Alloc(); }
B::B(const char *ch, unsigned int i){ id = B_id++; CName = clB; FuncName = ch; LineNumber = i; PrintCtor(); Alloc(); }
/*********************************** Class A *********************************/ class A : public C { public: A(); A(int) { id = A_id++; CName = clA; PrintCtor(); Alloc(); } A(const A&); A(const char *ch, unsigned int i); A operator+(A a); };
A::A() { id = A_id++; CName = clA; PrintCtor(); Alloc(); }
A::A(const A &b) { id = A_id++; CName = clA; PrintCtor(b.id); Alloc(); }
A::A(const char *ch, unsigned int i){ id = A_id++; CName = clA; FuncName = ch; LineNumber = i; PrintCtor(); Alloc(); }
void ThrowA() { A0; throw a0; }
void ThrowB() { B0; throw b0; }
void SehThrow() { RaiseException(STATUS_INTEGER_OVERFLOW, 0, 0, NULL); }
void Rethrow() { A0; throw; }
int SehFilter(EXCEPTION_POINTERS *pExPtrs, unsigned int ExceptionCode) { if (pExPtrs->ExceptionRecord->ExceptionCode == ExceptionCode) return EXCEPTION_EXECUTE_HANDLER; else return EXCEPTION_CONTINUE_SEARCH; }
/*********************************** Test 1 *********************************/
void Test1foo(void) { A0; try { throw; // first rethrow
} catch(A) { A1; DbgPrint("my exception\n"); } catch(...) { A2; DbgPrint("an other exception\n"); } }
int Test1() { A0; try { A1; try { A2; throw A(); } catch(...) { A3; Test1foo(); throw; // 2nd rethrow -- will result in ACCESS VIOLATION error
} } catch (...) { A4; try { A5; throw; } catch (A &e) { A6; e.print(); } catch(...) { A7; } }
return 0; } /*********************************** Test 2 *********************************/ void goandfail() { DbgPrint( "throwing in goandfail\n" ); throw (long)10; }
void dosomething() { A0; try { A1; goandfail(); } catch( long & sc ) { A2; DbgPrint( "catch in dosomething\n" ); throw sc; } }
class BTest2 : public B { char * _p; public: BTest2() : _p(0) {} ~BTest2() { try { A1; dosomething(); } catch( long & sc ) { A2; DbgPrint( "catch in ~B\n" ); }
delete [] _p; }
void print() { DbgPrint("BTest2 _p = %p\n", _p ); B::print(); }
};
int Test2() { DbgPrint( "top\n" );
try { A1; BTest2 b; b.print(); goandfail(); } catch( long & sc ) { A2; DbgPrint( "catch in main\n" ); }
DbgPrint( "all done\n" );
return 0; }
/*********************************** Test 3 *********************************/ void Test3() { A0; try { A1; char* pStr = NULL; try { A2; throw "1st throw\n"; } catch( char* str ) { A3; DbgPrint("%s%s", "A ", str); try { A4; throw "2nd throw\n"; } catch( char* str ) { A5; DbgPrint("%s%s", "B ", str); } throw; } } catch ( char* str ) { A6; DbgPrint("%s%s", "C ", str); } DbgPrint("Done\n"); } /*********************************** Test 4 *********************************/
void SehTest4() { int i; __try{ i = 0; ThrowA(); } __finally { if (i) { DbgPrint("Error: Finally in same function called %2d times\n", i+1); Fail = 1; } i++; } }
void Test4foo() { A0; try { A1; try { A2; SehTest4(); } catch(A ac) { A3; ThrowB(); } } catch(B bc) { A4; throw; }; }
void Test4boo() { A0; try{ A1; Test4foo(); } catch (B bc) { A2; SehThrow(); } }
void Test4() { __try { Test4boo(); } __except(1) { DbgPrint("Test4: Test4 __except\n"); } } /*********************************** Test 5 *********************************/
void SehTest5() { int i; __try{ i = 0; ThrowA(); } __finally { i++; if (i-1) { DbgPrint("Error: Finally in same function called %2d times\n", i); Fail = 1; } else { SehThrow(); } } }
void Test5foo() { A0; try { A1; try { A2; SehTest5(); } catch (...) { A3; } } catch (...) { A4; }; }
void Test5() { __try { Test5foo(); } __except(1) { DbgPrint("Test5: Test5 __except\n"); } }
void Test5Seh() { __try { SehTest5(); } __except(1) { DbgPrint("Test5: Test5 __except\n"); } }
/*********************************** Test 6 *********************************/ void Test6SeTrans( unsigned int u, EXCEPTION_POINTERS*pExp) { B0; if (pExp->ExceptionRecord->ExceptionCode == STATUS_INTEGER_OVERFLOW) throw b0; }
void Test6TTrans() { static int i = 0; A0; try { A1; SehThrow(); } catch (B b) { if (i == 0) { i++; Rethrow(); } else { ThrowB(); } } }
void Test6SehFunc() { __try { Test6TTrans(); } __except(SehFilter(exception_info(), STATUS_INTEGER_OVERFLOW)) { DbgPrint("In Test6SehFunc __except\n"); } }
void Test6CppFunc() { int i = 0; A0; try { A1; Test6SehFunc(); } catch(B b) { A2; DbgPrint("Error: Test6CppFunc catch(B b)\n"); Fail = 1; } try { try { A3; Test6SehFunc(); } catch(B b) { A4; i = 1; } } catch(...) { DbgPrint("Error: Missed catch(B b) in Test6CppFunc\n"); Fail = 1; } }
void Test6() { __try { _set_se_translator(Test6SeTrans); Test6CppFunc(); } __except(1) { DbgPrint("Error: Test6 __except\n"); Fail = 1; } _set_se_translator(NULL); }
/*********************************** Test 7 *********************************/
void Test7();
void Test7foo() { static int i = 0; A0; try { if (i == 0) SehThrow(); else Rethrow(); } catch(...) { if (i++ == 0) Test7(); else Rethrow(); } }
void Test7() { static int i = 0; int j = i++; __try { Test7foo(); } __except(SehFilter(exception_info(), STATUS_INTEGER_OVERFLOW)) { if (j == 0) { DbgPrint("Error: missed one Except After rethrow\n"); Fail = 1; } } }
/*********************************** Test 8 *********************************/
void Test8() { A0; try{ A1; try { ThrowB(); } catch (B b1) { try { A2; throw a2; } catch (A a) { A3; } throw; } } catch (B b2) { A4; } } int TestOver() { int i; int ret = 0; for (i = 0; i < NumMaxB; i++) { if (BObject[i] > 0) { DbgPrint("Error: id#%4d for B not destructed\n", i); ret = 1; } else if (BObject[i] < 0) { DbgPrint("Error: id#%4d for B destructed %d times", i, 1-AObject[i]); ret = 1; } BObject[i] = 0; } for (i = 0; i < NumMaxA; i++) { if (AObject[i] > 0) { DbgPrint("Error: id#%4d for A not destructed\n", i); ret = 1; } else if (AObject[i] < 0) { DbgPrint("Error: id#%4d for A destructed %d times", i, 1-AObject[i]); ret = 1; } AObject[i] = 0; } if (Fail) { ret = 1; Fail = 0; } A_id = B_id = 0; return ret; }
/*********************************** Test 9 *********************************/
struct TEST9 { int i; TEST9() { A0; i = 0; } ~TEST9() { A0; try { A1; ThrowB(); } catch (B) { A2; } } };
void Test9TEST() { TEST9 T; ThrowA(); }
void Test9() { A0; try { A1; Test9TEST(); } catch (A a) { A2; } }
main() { int i;
DbgBreakPoint();
__try { for (i = 0; i < NumTests; i++) { switch (i) { case 0: Test1(); break; case 1: Test2(); break; case 2: Test3(); break; case 3: Test4(); break; case 4: Test5(); DbgPrint("One live B expected\n"); break; case 5: Test6(); break; case 6: Test7(); break; case 7: Test8(); break; case 8: Test9(); break; } if (TestOver()) { DbgPrint("TEST#%2d FAILED\n", i+1); } else { DbgPrint("TEST#%2d PASSED\n", i+1); } } } __except(DbgBreakPoint()) { } }
|