1 // This fails for VxWorks RTPs because the initialization of 2 // __cxa_allocate_exception's emergency buffer mutex will 3 // itself call malloc(), and will fail if there is no more 4 // memory available. 5 // { dg-do run { xfail { { xstormy16-*-* *-*-darwin[3-7]* } || vxworks_rtp } } } 6 // Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. 7 // Contributed by Nathan Sidwell 6 June 2000 <nathan (at) codesourcery.com> 8 9 // Check we can throw a bad_alloc exception when malloc dies. 10 11 typedef __SIZE_TYPE__ size_t; 12 extern "C" void abort(); 13 extern "C" void *memcpy(void *, const void *, size_t); 14 15 // Assume that STACK_SIZE defined implies a system that does not have a 16 // large data space either, and additionally that we're not linking against 17 // a shared libstdc++ (which requires quite a bit more initialization space). 18 #ifdef STACK_SIZE 19 const int arena_size = 256; 20 #else 21 #if defined(__FreeBSD__) || defined(__sun__) || defined(__hpux__) 22 // FreeBSD, Solaris and HP-UX with threads require even more 23 // space at initialization time. FreeBSD 5 now requires over 131072 bytes. 24 const int arena_size = 262144; 25 #else 26 const int arena_size = 32768; 27 #endif 28 #endif 29 30 struct object 31 { 32 size_t size __attribute__((aligned)); 33 }; 34 35 static char arena[arena_size] __attribute__((aligned)); 36 static size_t pos; 37 38 // So we can force a failure when needed. 39 static int fail; 40 41 extern "C" void *malloc (size_t size) 42 { 43 object *p = reinterpret_cast<object *>(&arena[pos]); 44 45 if (fail) 46 return 0; 47 48 p->size = size; 49 size = (size + __alignof__(object) - 1) & - __alignof__(object); 50 pos += size + sizeof(object); 51 52 // Verify that we didn't run out of memory before getting initialized. 53 if (pos > arena_size) 54 abort (); 55 56 return p + 1; 57 } 58 59 extern "C" void free (void *) 60 { 61 } 62 63 extern "C" void *realloc (void *p, size_t size) 64 { 65 void *r; 66 67 if (p) 68 { 69 object *o = reinterpret_cast<object *>(p) - 1; 70 size_t old_size = o->size; 71 72 if (old_size >= size) 73 { 74 r = p; 75 o->size = size; 76 } 77 else 78 { 79 r = malloc (size); 80 memcpy (r, p, old_size); 81 free (p); 82 } 83 } 84 else 85 r = malloc (size); 86 87 return r; 88 } 89 90 void fn_throw() throw(int) 91 { 92 throw 1; 93 } 94 95 void fn_rethrow() throw(int) 96 { 97 try{fn_throw();} 98 catch(int a){ 99 throw;} 100 } 101 102 void fn_catchthrow() throw(int) 103 { 104 try{fn_throw();} 105 catch(int a){ 106 throw a + 1;} 107 } 108 109 int main() 110 { 111 /* On some systems (including FreeBSD and Solaris 2.10), 112 __cxa_get_globals will try to call "malloc" when threads are in 113 use. Therefore, we throw one exception up front so that 114 __cxa_get_globals is all set up. Ideally, this would not be 115 necessary, but it is a well-known idiom, and using this technique 116 means that we can still validate the fact that exceptions can be 117 thrown when malloc fails. */ 118 try{fn_throw();} 119 catch(int a){} 120 121 fail = 1; 122 123 try{fn_throw();} 124 catch(int a){} 125 126 try{fn_rethrow();} 127 catch(int a){} 128 129 try{fn_catchthrow();} 130 catch(int a){} 131 132 return 0; 133 } 134