1 // Copyright (c) Microsoft. All rights reserved. 2 // Licensed under the MIT license. See LICENSE file in the project root for 3 // full license information. 4 5 /* 6 ** The first call to Test checks to make sure that we don't call terminate 7 ** when an SEH fault is triggered. After catching the SEH fault, we then 8 ** cause a C++ EH fault (where the destructed object is in the try-block 9 ** that threw the exception). The C++ EH fault in the dtor should cause 10 ** a call to terminate(); in this case, we register our own handler to 11 ** trap the call to terminate(). We then run a second C++ EH fault (where 12 ** the destructed object is higher in the call tree than where the 13 ** exception was thrown). We trap this call to terminate() as well (with 14 ** a different handler) and then exit. 15 */ 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <eh.h> 20 21 int FGenSEHException; 22 23 class C 24 { 25 public: 26 C() {} 27 ~C() 28 { 29 printf( "in C::~C()\n"); 30 if (FGenSEHException) 31 { 32 printf("generating access violation (SEH)\n"); 33 *(volatile char*)(0) = 0; // Uh, EHa, don't you think? 34 } 35 else 36 { 37 printf("throwing C++ exception\n"); 38 throw 'a'; 39 } 40 } 41 }; 42 43 int Test() 44 { 45 try 46 { 47 C c; 48 throw 1; 49 } 50 catch (int) 51 { 52 printf("Destructor was not invoked \n"); 53 } 54 catch (char) 55 { 56 printf("Destructor exited using an exception\n"); 57 } 58 #if 0 59 catch (...) 60 { 61 printf("Throw caught by wrong handler\n"); 62 } 63 #endif 64 65 printf("terminate() was not called\n"); 66 67 return 1; 68 } 69 70 void Bar(void) 71 { 72 printf("in %s\n", __FUNCTION__); 73 throw 1; 74 } 75 76 void Test2(void) 77 { 78 printf("in %s\n", __FUNCTION__); 79 C c; 80 Bar(); 81 return; 82 } 83 84 void __cdecl Terminate2(void) 85 { 86 printf("termination handler (%s) called\n", __FUNCTION__); 87 exit(0); 88 } 89 90 void __cdecl Terminate1(void) 91 { 92 printf("termination handler (%s) called\n", __FUNCTION__); 93 94 // Set a new handler and run a second C++ EH test case. 95 set_terminate(Terminate2); 96 Test2(); 97 exit(0); 98 } 99 100 int main(void) 101 { 102 int i; 103 104 // First check that we don't terminate on an SEH exception 105 FGenSEHException = 1; 106 __try 107 { 108 i = Test(); 109 } 110 __except (1) 111 { 112 printf("caught SEH exception in %s\n", __FUNCTION__); 113 } 114 115 // Now set our own terminate handler and throw a C++ EH exception 116 set_terminate(Terminate1); 117 FGenSEHException = 0; 118 i = Test(); 119 120 // Should never get here 121 printf("termination handler not called\n"); 122 return i; 123 } 124