You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
768 lines
14 KiB
768 lines
14 KiB
#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()) {
|
|
}
|
|
}
|