Line data Source code
1 : //------------------------------------------------------------------------------ 2 : // LG_brutal_malloc: brutal memory debugging 3 : //------------------------------------------------------------------------------ 4 : 5 : // LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved. 6 : // SPDX-License-Identifier: BSD-2-Clause 7 : // 8 : // For additional details (including references to third party source code and 9 : // other files) see the LICENSE file or contact permission@sei.cmu.edu. See 10 : // Contributors.txt for a full list of contributors. Created, in part, with 11 : // funding and support from the U.S. Government (see Acknowledgments.txt file). 12 : // DM22-0790 13 : 14 : // Contributed by Timothy A. Davis, Texas A&M University 15 : 16 : //------------------------------------------------------------------------------ 17 : 18 : // To enable brutal memory debugging, these four functions must be passed to 19 : // LAGr_Init. 20 : 21 : #include "LG_internal.h" 22 : #include "LG_test.h" 23 : 24 : //------------------------------------------------------------------------------ 25 : // global variables: LG_brutal and LG_nmalloc 26 : //------------------------------------------------------------------------------ 27 : 28 : // If LG_brutal >= 0, then that value gives the # of malloc/calloc/realloc 29 : // calls that will succeed. Each time malloc/calloc/realloc is called, the 30 : // LG_brutal count is decremented. Once it reaches zero, no more memory 31 : // allocations will occur, and LG_brutal_malloc, etc, all pretend to fail 32 : // and return NULL. 33 : 34 : // If LG_brutal is negative, the LG_brutal_malloc/calloc/realloc functions act 35 : // like the regular malloc/calloc/realloc functions, with no pretend failures. 36 : 37 : // LG_nmalloc is the count of the # of allocated blocks. It is incremented by 38 : // LG_brutal_malloc/calloc and by LG_brutal_realloc if a new block is allocated. 39 : // It is decremented by LG_brutal_free. After LAGraph_Finalize is called, 40 : // this value should be zero. If nonzero, a memory leak has occured. 41 : 42 : LG_TEST_PUBLIC int64_t LG_brutal = -1 ; 43 : LG_TEST_PUBLIC int64_t LG_nmalloc = 0 ; 44 : 45 : //------------------------------------------------------------------------------ 46 : // LG_brutal_malloc 47 : //------------------------------------------------------------------------------ 48 : 49 : LG_TEST_PUBLIC 50 918370 : void *LG_brutal_malloc // return pointer to allocated block of memory 51 : ( 52 : size_t size // # of bytes to allocate 53 : ) 54 : { 55 : void *p ; 56 918370 : if (LG_brutal == 0) 57 : { 58 : // pretend to fail 59 37834 : p = NULL ; 60 : } 61 : else 62 : { 63 : // malloc a new block 64 : #pragma omp critical (LG_brutal_malloc_critical) 65 : { 66 : // malloc the block of memory (of size at least 1 byte) 67 880536 : p = malloc (LAGRAPH_MAX (1, size)) ; 68 880536 : if (LG_brutal > 0) 69 : { 70 : // one step closer to pretending to fail 71 863933 : LG_brutal-- ; 72 : } 73 880536 : if (p != NULL) 74 : { 75 : // one more block of memory successfully allocated 76 880536 : LG_nmalloc++ ; 77 : } 78 : } 79 : } 80 918370 : return (p) ; 81 : } 82 : 83 : //------------------------------------------------------------------------------ 84 : // LG_brutal_calloc 85 : //------------------------------------------------------------------------------ 86 : 87 : LG_TEST_PUBLIC 88 681 : void *LG_brutal_calloc // return pointer to allocated block of memory 89 : ( 90 : size_t nitems, // # of items to allocate 91 : size_t itemsize // # of bytes per item 92 : ) 93 : { 94 681 : size_t size = LAGRAPH_MAX (1, nitems * itemsize) ; 95 681 : void *p = LG_brutal_malloc (size) ; 96 681 : if (p != NULL) 97 : { 98 680 : memset (p, 0, size) ; 99 : } 100 681 : return (p) ; 101 : } 102 : 103 : //------------------------------------------------------------------------------ 104 : // LG_brutal_free 105 : //------------------------------------------------------------------------------ 106 : 107 : LG_TEST_PUBLIC 108 880536 : void LG_brutal_free 109 : ( 110 : void *p // block to free 111 : ) 112 : { 113 880536 : if (p != NULL) 114 : { 115 : #pragma omp critical (LG_brutal_malloc_critical) 116 : { 117 : // free the block 118 880536 : free (p) ; 119 : // one less block of memory allocated 120 880536 : LG_nmalloc-- ; 121 : } 122 : } 123 880536 : } 124 : 125 : //------------------------------------------------------------------------------ 126 : // LG_brutal_realloc 127 : //------------------------------------------------------------------------------ 128 : 129 : LG_TEST_PUBLIC 130 25016 : void *LG_brutal_realloc // return pointer to reallocated memory 131 : ( 132 : void *p, // block to realloc 133 : size_t size // new size of the block 134 : ) 135 : { 136 25016 : if (p == NULL) 137 : { 138 : // malloc a new block 139 4 : p = LG_brutal_malloc (size) ; 140 : } 141 : else 142 : { 143 : // realloc an existing block 144 : #pragma omp critical (LG_brutal_malloc_critical) 145 : { 146 25012 : if (LG_brutal == 0) 147 : { 148 : // pretend to fail 149 658 : p = NULL ; 150 : } 151 : else 152 : { 153 : // realloc the block 154 24354 : p = realloc (p, size) ; 155 24354 : if (LG_brutal > 0) 156 : { 157 : // one step closer to pretending to fail 158 24327 : LG_brutal-- ; 159 : } 160 : } 161 : } 162 : } 163 25016 : return (p) ; 164 : }