ARB
arb_mem.cxx
Go to the documentation of this file.
1 // ================================================================= //
2 // //
3 // File : arb_mem.cxx //
4 // Purpose : "Failsafe" memory handlers //
5 // ("succeed or terminate"!) //
6 // //
7 // Coded by Elmar Pruesse and Ralf Westram //
8 // http://www.arb-home.de/ //
9 // //
10 // ================================================================= //
11 
12 #include "arb_mem.h"
13 #include "arb_msg.h"
14 
15 static char panicBuffer[500] = { 0 };
16 
18  arb_assert(panicBuffer[0]); // sth should have been printed into buffer
19 
20  fputs("\n--------------------\n", stderr);
21  fputs(panicBuffer, stderr);
22  fputs("\n"
23  "To avoid memory allocation problems\n"
24  " - increase your swap space (see 'man 8 mkswap'),\n"
25  " - reduce the amount of data (used for the failing operation)\n"
26  " - or buy more memory.\n"
27  "\n"
28  "The program will terminate now!\n\n",
29  stderr);
30 
31  GBK_terminate(panicBuffer);
32 }
33 
34 void arb_mem::failed_to_allocate(const char *reason) {
35  sprintf(panicBuffer, "Failed to allocate memory: %s", reason);
37 }
38 void arb_mem::failed_to_allocate(size_t size) {
39  sprintf(panicBuffer, "Failed to allocate memory (tried to get %zu bytes)", size);
41 }
42 void arb_mem::failed_to_allocate(size_t nelem, size_t elsize) {
43  if (nelem == 1) failed_to_allocate(elsize);
44  if (elsize == 1) failed_to_allocate(nelem);
45  sprintf(panicBuffer, "Failed to allocate memory (tried to get %zu*%zu bytes)", nelem, elsize);
47 }
48 
49 
50 // --------------------------------------------------------------------------------
51 
52 #ifdef UNIT_TESTS
53 #ifndef TEST_UNIT_H
54 #include <test_unit.h>
55 #endif
56 
57 #if !defined(LEAKS_SANITIZED) && !defined(__clang__) && defined(ENABLE_CRASH_TESTS)
58 // @@@ TEST_DISABLED_CLANG: clang version fails to segfault after allocation failure. needs fix.
59 # define TEST_ALLOC_SEGFAULTS
60 #endif
61 
62 #if defined(TEST_ALLOC_SEGFAULTS)
63 static size_t TOO_MUCH = 1; // changed before use (to avoid "-Walloc-size-larger-than=" warning)
64 
65 static void alloc_too_much() { ARB_alloc<char>(TOO_MUCH); }
66 static void calloc_too_much() { ARB_calloc<char>(TOO_MUCH); }
67 static void realloc_too_much() { char *s = NULp; ARB_realloc(s, TOO_MUCH); }
68 static void recalloc_too_much() { char *s = NULp; ARB_recalloc(s, 0, TOO_MUCH); }
69 
70 #endif
71 
72 static bool mem_is_cleared(const char *mem, size_t size) {
73  for (size_t s = 0; s<size; ++s) {
74  if (mem[s]) return false;
75  }
76  return true;
77 }
78 
79 void TEST_allocators__crashtest() {
80  const int SIZE = 100;
81  const int SIZE2 = 200;
82  char *s = NULp; TEST_EXPECT_NULL(s);
83 
84  s = ARB_alloc<char>(0); TEST_REJECT_NULL((void*)s); // allocating empty block works
85  freeset(s, ARB_alloc<char>(SIZE)); TEST_REJECT_NULL((void*)s);
86 
87  freenull(s); TEST_EXPECT_NULL(s);
88 
89  ARB_realloc(s, 0); TEST_REJECT_NULL((void*)s);
90  ARB_realloc(s, SIZE); TEST_REJECT_NULL((void*)s);
91  // ARB_realloc(s, 0); TEST_REJECT_NULL(s); // fails
92 
93  freenull(s); TEST_EXPECT_NULL(s);
94 
95  s = ARB_calloc<char>(0); TEST_REJECT_NULL((void*)s);
96  freeset(s, ARB_calloc<char>(SIZE)); TEST_REJECT_NULL((void*)s); TEST_EXPECT(mem_is_cleared(s, SIZE));
97 
98  freenull(s); TEST_EXPECT_NULL(s);
99 
100  ARB_recalloc(s, 0, 1); TEST_REJECT_NULL((void*)s); TEST_EXPECT(mem_is_cleared(s, 1));
101  ARB_recalloc(s, 1, SIZE); TEST_REJECT_NULL((void*)s); TEST_EXPECT(mem_is_cleared(s, SIZE));
102  ARB_recalloc(s, SIZE, SIZE2); TEST_REJECT_NULL((void*)s); TEST_EXPECT(mem_is_cleared(s, SIZE2));
103  ARB_recalloc(s, SIZE2, SIZE); TEST_REJECT_NULL((void*)s); TEST_EXPECT(mem_is_cleared(s, SIZE));
104  ARB_recalloc(s, SIZE, 1); TEST_REJECT_NULL((void*)s); TEST_EXPECT(mem_is_cleared(s, 1));
105  // ARB_recalloc(s, 1, 0); TEST_REJECT_NULL(s); // fails
106 
107  freenull(s); TEST_EXPECT_NULL(s);
108 
109 #if defined(TEST_ALLOC_SEGFAULTS)
110  // test out-of-mem = > terminate
111 
112  TOO_MUCH = -1;
113 
114  TEST_EXPECT_SEGFAULT(alloc_too_much);
115  TEST_EXPECT_SEGFAULT(calloc_too_much);
116  TEST_EXPECT_SEGFAULT(realloc_too_much);
117  TEST_EXPECT_SEGFAULT(recalloc_too_much);
118 #endif
119 }
120 
121 #endif // UNIT_TESTS
122 
123 // --------------------------------------------------------------------------------
124 
#define arb_assert(cond)
Definition: arb_assert.h:245
static __ATTR__NORETURN void alloc_failure_panic()
Definition: arb_mem.cxx:17
#define TEST_EXPECT(cond)
Definition: test_unit.h:1328
void GBK_terminate(const char *error) __ATTR__NORETURN
Definition: arb_msg.cxx:509
#define TEST_REJECT_NULL(n)
Definition: test_unit.h:1325
#define SIZE
Definition: date.cxx:7
static char panicBuffer[500]
Definition: arb_mem.cxx:15
void ARB_recalloc(TYPE *&tgt, size_t oelem, size_t nelem)
Definition: arb_mem.h:49
void failed_to_allocate(const char *reason) __ATTR__NORETURN
Definition: arb_mem.cxx:34
fputs(TRACE_PREFIX, stderr)
#define TEST_EXPECT_NULL(n)
Definition: test_unit.h:1322
void ARB_realloc(TYPE *&tgt, size_t nelem)
Definition: arb_mem.h:43
#define TEST_EXPECT_SEGFAULT(cb)
Definition: test_unit.h:1255
#define NULp
Definition: cxxforward.h:116
#define __ATTR__NORETURN
Definition: attributes.h:56
GB_write_int const char s
Definition: AW_awar.cxx:154