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