source: branches/alilink/CORE/arb_mem.cxx

Last change on this file was 18126, checked in by westram, 5 years ago
File size: 4.9 KB
Line 
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
15static char panicBuffer[500] = { 0 };
16
17static __ATTR__NORETURN void alloc_failure_panic() {
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
34void arb_mem::failed_to_allocate(const char *reason) {
35    sprintf(panicBuffer, "Failed to allocate memory: %s", reason);
36    alloc_failure_panic();
37}
38void arb_mem::failed_to_allocate(size_t size) {
39    sprintf(panicBuffer, "Failed to allocate memory (tried to get %zu bytes)", size);
40    alloc_failure_panic();
41}
42void 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);
46    alloc_failure_panic();
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)
63static size_t TOO_MUCH = 1; // changed before use (to avoid "-Walloc-size-larger-than=" warning)
64
65static void alloc_too_much()    { ARB_alloc<char>(TOO_MUCH); }
66static void calloc_too_much()   { ARB_calloc<char>(TOO_MUCH); }
67static void realloc_too_much()  { char *s = NULp; ARB_realloc(s, TOO_MUCH); }
68static void recalloc_too_much() { char *s = NULp; ARB_recalloc(s, 0, TOO_MUCH); }
69
70#endif
71
72static 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
79void 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
Note: See TracBrowser for help on using the repository browser.