Heap.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (c) 2009, 2020 IBM Corp.
3  *
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v2.0
6  * and Eclipse Distribution License v1.0 which accompany this distribution.
7  *
8  * The Eclipse Public License is available at
9  * https://www.eclipse.org/legal/epl-2.0/
10  * and the Eclipse Distribution License is available at
11  * http://www.eclipse.org/org/documents/edl-v10.php.
12  *
13  * Contributors:
14  * Ian Craggs - initial API and implementation and/or initial documentation
15  * Ian Craggs - use tree data structure instead of list
16  * Ian Craggs - change roundup to Heap_roundup to avoid macro name clash on MacOSX
17  *******************************************************************************/
18 
29 #include "Tree.h"
30 #include "Log.h"
31 #include "StackTrace.h"
32 #include "Thread.h"
33 
34 #if defined(HEAP_UNIT_TESTS)
35 char* Broker_recordFFDC(char* symptoms);
36 #endif /* HEAP_UNIT_TESTS */
37 
38 #include <stdlib.h>
39 #include <string.h>
40 #include <stdio.h>
41 #include <stddef.h>
42 
43 #include "Heap.h"
44 
45 #if !defined(NO_HEAP_TRACKING)
46 
47 #undef malloc
48 #undef realloc
49 #undef free
50 
51 #if defined(_WIN32) || defined(_WIN64)
53 #else
54 static pthread_mutex_t heap_mutex_store = PTHREAD_MUTEX_INITIALIZER;
56 #endif
57 
58 static heap_info state = {0, 0};
60 typedef double eyecatcherType;
61 static eyecatcherType eyecatcher = (eyecatcherType)0x8888888888888888;
62 
63 /*#define HEAP_STACK 1 */
64 
68 typedef struct
69 {
70  char* file;
71  int line;
72  void* ptr;
73  size_t size;
74 #if defined(HEAP_STACK)
75  char* stack;
76 #endif
78 
79 static Tree heap;
80 static const char *errmsg = "Memory allocation error";
81 
82 
83 static size_t Heap_roundup(size_t size);
84 static int ptrCompare(void* a, void* b, int value);
85 /*static void Heap_check(char* string, void* ptr);*/
86 static void checkEyecatchers(char* file, int line, void* p, size_t size);
87 static int Internal_heap_unlink(char* file, int line, void* p);
88 static void HeapScan(enum LOG_LEVELS log_level);
89 
90 
98 static size_t Heap_roundup(size_t size)
99 {
100  static int multsize = 4*sizeof(int);
101 
102  if (size % multsize != 0)
103  size += multsize - (size % multsize);
104  return size;
105 }
106 
107 
114 static int ptrCompare(void* a, void* b, int value)
115 {
116  a = ((storageElement*)a)->ptr;
117  if (value)
118  b = ((storageElement*)b)->ptr;
119 
120  return (a > b) ? -1 : (a == b) ? 0 : 1;
121 }
122 
123 /*
124 static void Heap_check(char* string, void* ptr)
125 {
126  Node* curnode = NULL;
127  storageElement* prev, *s = NULL;
128 
129  printf("Heap_check start %p\n", ptr);
130  while ((curnode = TreeNextElement(&heap, curnode)) != NULL)
131  {
132  prev = s;
133  s = (storageElement*)(curnode->content);
134 
135  if (prev)
136  {
137  if (ptrCompare(s, prev, 1) != -1)
138  {
139  printf("%s: heap order error %d %p %p\n", string, ptrCompare(s, prev, 1), prev->ptr, s->ptr);
140  exit(99);
141  }
142  else
143  printf("%s: heap order good %d %p %p\n", string, ptrCompare(s, prev, 1), prev->ptr, s->ptr);
144  }
145  }
146 }*/
147 
148 
158 void* mymalloc(char* file, int line, size_t size)
159 {
160  storageElement* s = NULL;
161  size_t space = sizeof(storageElement);
162  size_t filenamelen = strlen(file)+1;
163  void* rc = NULL;
164 
166  size = Heap_roundup(size);
167  if ((s = malloc(sizeof(storageElement))) == NULL)
168  {
169  Log(LOG_ERROR, 13, errmsg);
170  goto exit;
171  }
172  memset(s, 0, sizeof(storageElement));
173 
174  s->size = size; /* size without eyecatchers */
175  if ((s->file = malloc(filenamelen)) == NULL)
176  {
177  Log(LOG_ERROR, 13, errmsg);
178  free(s);
179  goto exit;
180  }
181  memset(s->file, 0, sizeof(filenamelen));
182 
183  space += filenamelen;
184  strcpy(s->file, file);
185 #if defined(HEAP_STACK)
186 #define STACK_LEN 300
187  if ((s->stack = malloc(STACK_LEN)) == NULL)
188  {
189  Log(LOG_ERROR, 13, errmsg);
190  free(s->file);
191  free(s);
192  goto exit;
193  }
194  memset(s->stack, 0, sizeof(filenamelen));
195  StackTrace_get(Thread_getid(), s->stack, STACK_LEN);
196 #endif
197  s->line = line;
198  /* Add space for eyecatcher at each end */
199  if ((s->ptr = malloc(size + 2*sizeof(eyecatcherType))) == NULL)
200  {
201  Log(LOG_ERROR, 13, errmsg);
202  free(s->file);
203  free(s);
204  goto exit;
205  }
206  memset(s->ptr, 0, size + 2*sizeof(eyecatcherType));
207  space += size + 2*sizeof(eyecatcherType);
208  *(eyecatcherType*)(s->ptr) = eyecatcher; /* start eyecatcher */
209  *(eyecatcherType*)(((char*)(s->ptr)) + (sizeof(eyecatcherType) + size)) = eyecatcher; /* end eyecatcher */
210  Log(TRACE_MAX, -1, "Allocating %d bytes in heap at file %s line %d ptr %p\n", (int)size, file, line, s->ptr);
211  TreeAdd(&heap, s, space);
212  state.current_size += size;
213  if (state.current_size > state.max_size)
214  state.max_size = state.current_size;
215  rc = ((eyecatcherType*)(s->ptr)) + 1; /* skip start eyecatcher */
216 exit:
218  return rc;
219 }
220 
221 
222 static void checkEyecatchers(char* file, int line, void* p, size_t size)
223 {
224  eyecatcherType *sp = (eyecatcherType*)p;
225  char *cp = (char*)p;
226  eyecatcherType us;
227  static const char *msg = "Invalid %s eyecatcher %d in heap item at file %s line %d";
228 
229  if ((us = *--sp) != eyecatcher)
230  Log(LOG_ERROR, 13, msg, "start", us, file, line);
231 
232  cp += size;
233  if ((us = *(eyecatcherType*)cp) != eyecatcher)
234  Log(LOG_ERROR, 13, msg, "end", us, file, line);
235 }
236 
237 
245 static int Internal_heap_unlink(char* file, int line, void* p)
246 {
247  Node* e = NULL;
248  int rc = 0;
249 
250  e = TreeFind(&heap, ((eyecatcherType*)p)-1);
251  if (e == NULL)
252  Log(LOG_ERROR, 13, "Failed to remove heap item at file %s line %d", file, line);
253  else
254  {
255  storageElement* s = (storageElement*)(e->content);
256  Log(TRACE_MAX, -1, "Freeing %d bytes in heap at file %s line %d, heap use now %d bytes\n",
257  (int)s->size, file, line, (int)state.current_size);
258  checkEyecatchers(file, line, p, s->size);
259  /* free(s->ptr); */
260  free(s->file);
261  state.current_size -= s->size;
262  TreeRemoveNodeIndex(&heap, e, 0);
263  free(s);
264  rc = 1;
265  }
266  return rc;
267 }
268 
269 
277 void myfree(char* file, int line, void* p)
278 {
279  if (p) /* it is legal und usual to call free(NULL) */
280  {
282  if (Internal_heap_unlink(file, line, p))
283  free(((eyecatcherType*)p)-1);
285  }
286  else
287  {
288  Log(LOG_ERROR, -1, "Call of free(NULL) in %s,%d",file,line);
289  }
290 }
291 
292 
300 void Heap_unlink(char* file, int line, void* p)
301 {
303  Internal_heap_unlink(file, line, p);
305 }
306 
307 
320 void *myrealloc(char* file, int line, void* p, size_t size)
321 {
322  void* rc = NULL;
323  storageElement* s = NULL;
324 
326  s = TreeRemoveKey(&heap, ((eyecatcherType*)p)-1);
327  if (s == NULL)
328  Log(LOG_ERROR, 13, "Failed to reallocate heap item at file %s line %d", file, line);
329  else
330  {
331  size_t space = sizeof(storageElement);
332  size_t filenamelen = strlen(file)+1;
333 
334  checkEyecatchers(file, line, p, s->size);
335  size = Heap_roundup(size);
336  state.current_size += size - s->size;
337  if (state.current_size > state.max_size)
338  state.max_size = state.current_size;
339  if ((s->ptr = realloc(s->ptr, size + 2*sizeof(eyecatcherType))) == NULL)
340  {
341  Log(LOG_ERROR, 13, errmsg);
342  goto exit;
343  }
344  space += size + 2*sizeof(eyecatcherType) - s->size;
345  *(eyecatcherType*)(s->ptr) = eyecatcher; /* start eyecatcher */
346  *(eyecatcherType*)(((char*)(s->ptr)) + (sizeof(eyecatcherType) + size)) = eyecatcher; /* end eyecatcher */
347  s->size = size;
348  space -= strlen(s->file);
349  s->file = realloc(s->file, filenamelen);
350  space += filenamelen;
351  strcpy(s->file, file);
352  s->line = line;
353  rc = s->ptr;
354  TreeAdd(&heap, s, space);
355  }
356 exit:
358  return (rc == NULL) ? NULL : ((eyecatcherType*)(rc)) + 1; /* skip start eyecatcher */
359 }
360 
361 
368 void* Heap_findItem(void* p)
369 {
370  Node* e = NULL;
371 
373  e = TreeFind(&heap, ((eyecatcherType*)p)-1);
375  return (e == NULL) ? NULL : e->content;
376 }
377 
378 
383 static void HeapScan(enum LOG_LEVELS log_level)
384 {
385  Node* current = NULL;
386 
388  Log(log_level, -1, "Heap scan start, total %d bytes", (int)state.current_size);
389  while ((current = TreeNextElement(&heap, current)) != NULL)
390  {
391  storageElement* s = (storageElement*)(current->content);
392  Log(log_level, -1, "Heap element size %d, line %d, file %s, ptr %p", (int)s->size, s->line, s->file, s->ptr);
393  Log(log_level, -1, " Content %.*s", (10 > current->size) ? (int)s->size : 10, (char*)(((eyecatcherType*)s->ptr) + 1));
394 #if defined(HEAP_STACK)
395  Log(log_level, -1, " Stack:\n%s", s->stack);
396 #endif
397  }
398  Log(log_level, -1, "Heap scan end");
400 }
401 
402 
407 {
409  heap.heap_tracking = 0; /* no recursive heap tracking! */
410  return 0;
411 }
412 
413 
417 void Heap_terminate(void)
418 {
419  Log(TRACE_MIN, -1, "Maximum heap use was %d bytes", (int)state.max_size);
420  if (state.current_size > 20) /* One log list is freed after this function is called */
421  {
422  Log(LOG_ERROR, -1, "Some memory not freed at shutdown, possible memory leak");
424  }
425 }
426 
427 
433 {
434  return &state;
435 }
436 
437 
443 int HeapDumpString(FILE* file, char* str)
444 {
445  int rc = 0;
446  size_t len = str ? strlen(str) + 1 : 0; /* include the trailing null */
447 
448  if (fwrite(&(str), sizeof(char*), 1, file) != 1)
449  rc = -1;
450  else if (fwrite(&(len), sizeof(int), 1 ,file) != 1)
451  rc = -1;
452  else if (len > 0 && fwrite(str, len, 1, file) != 1)
453  rc = -1;
454  return rc;
455 }
456 
457 
462 int HeapDump(FILE* file)
463 {
464  int rc = 0;
465  Node* current = NULL;
466 
467  while (rc == 0 && (current = TreeNextElement(&heap, current)))
468  {
469  storageElement* s = (storageElement*)(current->content);
470 
471  if (fwrite(&(s->ptr), sizeof(s->ptr), 1, file) != 1)
472  rc = -1;
473  else if (fwrite(&(current->size), sizeof(current->size), 1, file) != 1)
474  rc = -1;
475  else if (fwrite(s->ptr, current->size, 1, file) != 1)
476  rc = -1;
477  }
478  return rc;
479 }
480 
481 #endif
482 
483 
484 #if defined(HEAP_UNIT_TESTS)
485 
486 void Log(enum LOG_LEVELS log_level, int msgno, char* format, ...)
487 {
488  printf("Log %s", format);
489 }
490 
491 char* Broker_recordFFDC(char* symptoms)
492 {
493  printf("recordFFDC");
494  return "";
495 }
496 
497 #define malloc(x) mymalloc(__FILE__, __LINE__, x)
498 #define realloc(a, b) myrealloc(__FILE__, __LINE__, a, b)
499 #define free(x) myfree(__FILE__, __LINE__, x)
500 
501 int main(int argc, char *argv[])
502 {
503  char* h = NULL;
504  Heap_initialize();
505 
506  h = malloc(12);
507  free(h);
508  printf("freed h\n");
509 
510  h = malloc(12);
511  h = realloc(h, 14);
512  h = realloc(h, 25);
513  h = realloc(h, 255);
514  h = realloc(h, 2225);
515  h = realloc(h, 22225);
516  printf("freeing h\n");
517  free(h);
518  Heap_terminate();
519  printf("Finishing\n");
520  return 0;
521 }
522 
523 #endif /* HEAP_UNIT_TESTS */
524 
525 /* Local Variables: */
526 /* indent-tabs-mode: t */
527 /* c-basic-offset: 8 */
528 /* End: */
enum MQTTPropertyCodes value
#define TRACE_MIN
Definition: Log.h:66
static heap_info state
Definition: Heap.c:58
void * TreeAdd(Tree *aTree, void *content, size_t size)
Definition: Tree.c:274
static pthread_mutex_t heap_mutex_store
Definition: Heap.c:54
FMT_INLINE std::basic_string< Char > format(const S &format_str, Args &&...args)
Definition: core.h:2081
static mutex_type heap_mutex
Definition: Heap.c:55
size_t max_size
Definition: Heap.h:65
int HeapDumpString(FILE *file, char *str)
Definition: Heap.c:443
void * Heap_findItem(void *p)
Definition: Heap.c:368
LOG_LEVELS
Definition: Log.h:35
void * TreeRemoveKey(Tree *aTree, void *key)
Definition: Tree.c:529
int Thread_lock_mutex(mutex_type mutex)
Definition: Thread.c:112
#define malloc(x)
Definition: Heap.h:41
void * myrealloc(char *file, int line, void *p, size_t size)
Definition: Heap.c:320
int line
Definition: Heap.c:71
void Heap_unlink(char *file, int line, void *p)
Definition: Heap.c:300
#define TRACE_MAX
Definition: Log.h:65
void * mymalloc(char *file, int line, size_t size)
Definition: Heap.c:158
char * StackTrace_get(thread_id_type threadid, char *buf, int bufsize)
Definition: StackTrace.c:175
#define free(x)
Definition: Heap.h:55
double eyecatcherType
Definition: Heap.c:60
static int Internal_heap_unlink(char *file, int line, void *p)
Definition: Heap.c:245
void * TreeRemoveNodeIndex(Tree *aTree, Node *curnode, int index)
Definition: Tree.c:420
static size_t Heap_roundup(size_t size)
Definition: Heap.c:98
void myfree(char *file, int line, void *p)
Definition: Heap.c:277
unsigned int heap_tracking
Definition: Tree.h:86
#define realloc(a, b)
Definition: Heap.h:49
void TreeInitializeNoMalloc(Tree *aTree, int(*compare)(void *, void *, int))
Definition: Tree.c:53
static const char * errmsg
Definition: Heap.c:80
Node * TreeNextElement(Tree *aTree, Node *curnode)
Definition: Tree.c:358
int Thread_unlock_mutex(mutex_type mutex)
Definition: Thread.c:133
void Log(enum LOG_LEVELS log_level, int msgno, const char *format,...)
Definition: Log.c:417
heap_info * Heap_get_info(void)
Definition: Heap.c:432
int HeapDump(FILE *file)
Definition: Heap.c:462
#define mutex_type
Definition: mutex_type.h:22
Definition: Log.h:41
void * ptr
Definition: Heap.c:72
char * file
Definition: Heap.c:70
size_t size
Definition: Heap.c:73
Definition: Tree.h:76
Node * TreeFind(Tree *aTree, void *key)
Definition: Tree.c:315
Definition: Heap.h:62
void Heap_terminate(void)
Definition: Heap.c:417
int Heap_initialize(void)
Definition: Heap.c:406
static void checkEyecatchers(char *file, int line, void *p, size_t size)
Definition: Heap.c:222
size_t current_size
Definition: Heap.h:64
thread_id_type Thread_getid(void)
Definition: Thread.c:176
static int ptrCompare(void *a, void *b, int value)
Definition: Heap.c:114
Definition: lobject.h:674
enum MQTTReasonCodes rc
Definition: test10.c:1112
static eyecatcherType eyecatcher
Definition: Heap.c:61
static Tree heap
Definition: Heap.c:79
int main(int argc, char **argv)
Definition: lua.c:619
int len
Definition: utf-8.c:46
static void HeapScan(enum LOG_LEVELS log_level)
Definition: Heap.c:383


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:47:35