FrontISTR  5.7.0
Large-scale structural analysis program with finit element method
hecmw_malloc.c
Go to the documentation of this file.
1 /*****************************************************************************
2  * Copyright (c) 2019 FrontISTR Commons
3  * This software is released under the MIT License, see LICENSE.txt
4  *****************************************************************************/
5 
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <errno.h>
10 #include "hecmw_config.h"
11 #include "hecmw_util.h"
12 #include "hecmw_malloc.h"
13 
14 struct malloc_info {
15  void *ptr;
16  size_t size;
17  char *file;
18  int line;
19  struct malloc_info *next;
20 };
21 
22 static struct malloc_info *mainfo;
23 
24 static int is_check_memleak;
25 
26 static long mem_size;
27 
28 static int auto_check = 1;
29 
30 static int n_ptr;
31 
32 static int add_info(void *ptr, size_t size, char *file, int line) {
33  static struct malloc_info *info;
34  int rtc;
35 
37 
38  #pragma omp critical
39  {
40  info = malloc(sizeof(*info));
41  if (info == NULL) {
42  rtc = -1;
43  } else {
44  mem_size += size;
45 
46  info->ptr = ptr;
47  info->size = size;
48  info->file = file;
49  info->line = line;
50  info->next = mainfo;
51 
52  mainfo = info;
53 
54  n_ptr++;
55  rtc = 0;
56  }
57  }
58 
59  return rtc;
60 }
61 
62 static int del_info(void *ptr) {
63  struct malloc_info *p, *q;
64  int rtc, i;
65 
67 
68  #pragma omp critical
69  {
70  q = NULL;
71  for (p = mainfo, i = 0; p && p->ptr != ptr; p = (q = p)->next, i++) {
72  HECMW_assert(i < n_ptr);
73  }
74  if (p == NULL) {
75  rtc = -1; /* not found */
76  } else {
77  if (q == NULL) {
78  mainfo = p->next;
79  } else {
80  q->next = p->next;
81  }
82  mem_size -= p->size;
83  free(p);
84 
85  n_ptr--;
86  rtc = 0;
87  }
88  }
89  return rtc;
90 }
91 
92 static int change_info(void *ptrold, void *ptrnew, size_t sizenew, char *file,
93  int line) {
94  struct malloc_info *p;
95  long size;
96  int rtc, i;
97 
98  HECMW_assert(ptrold);
99  HECMW_assert(ptrnew);
100 
101  #pragma omp critical
102  {
103  for (p = mainfo, i = 0; p && p->ptr != ptrold; p = p->next, i++) {
104  HECMW_assert(i < n_ptr);
105  }
106  if (p == NULL) {
107  rtc = -1;
108  } else {
109  size = sizenew - p->size;
110  mem_size += size;
111  p->ptr = ptrnew;
112  p->size = sizenew;
113  p->file = file;
114  p->line = line;
115  rtc = 0;
116  }
117  }
118  return rtc;
119 }
120 
121 int HECMW_list_meminfo(FILE *fp) {
122  int n;
123  struct malloc_info *p;
124 
125  if (fp == NULL) fp = stdout;
126 
127  n = 0;
128  for (p = mainfo; p; p = p->next) {
129  fprintf(fp, "HEC-MW memory info: %s:%d ptr=%p size=%d\n", p->file,
130  p->line, p->ptr, (int)p->size);
131  n++;
132  }
133  return n;
134 }
135 
136 void HECMW_set_autocheck_memleak(int flag) { auto_check = flag ? 1 : 0; }
137 
139  int n;
140  struct malloc_info *p;
141 
142  if (mainfo == NULL) return 0; /* no memory leaks */
143  n = 0;
144  for (p = mainfo; p; p = p->next) {
145  fprintf(stderr,
146  "HEC-MW memory check: "
147  "A memory leak found at %s:%d ptr=%p size=%d\n",
148  p->file, p->line, p->ptr, (int)p->size);
149  n++;
150  }
151  fprintf(stderr,
152  "HEC-MW memory check: "
153  "%d memory leak%s found\n",
154  n, (n > 1) ? "s" : "");
155  return n;
156 }
157 
158 static void check_memleak(void) { HECMW_check_memleak(); }
159 
160 static int mark_check_memleak(void) {
161  if (!is_check_memleak) {
162  if (atexit(check_memleak) == -1) return -1;
163  is_check_memleak = 1;
164  }
165  return 0;
166 }
167 
168 long HECMW_get_memsize(void) { return mem_size; }
169 
170 void HECMW_free_(void *ptr, char *file, int line) {
171  if (ptr == NULL) return;
172  if (del_info(ptr)) {
174  "Not found allocated memory %p(%s:%d)\n", ptr, file, line);
175  }
176  free(ptr);
177 }
178 
179 void *HECMW_malloc_(size_t size, char *file, int line) {
180  void *ptr = NULL;
181 
182  ptr = malloc(size);
183  if (ptr == NULL) goto error;
184  if (add_info(ptr, size, file, line)) goto error;
185  if (auto_check) {
186  if (mark_check_memleak()) goto error;
187  }
188  return ptr;
189 error:
190  free(ptr);
191  return NULL;
192 }
193 
194 void *HECMW_calloc_(size_t nmemb, size_t size, char *file, int line) {
195  void *ptr = NULL;
196 
197  ptr = calloc(nmemb, size);
198  if (ptr == NULL) goto error;
199  if (add_info(ptr, nmemb * size, file, line)) goto error;
200  if (auto_check) {
201  if (mark_check_memleak()) goto error;
202  }
203  return ptr;
204 error:
205  free(ptr);
206  return NULL;
207 }
208 
209 void *HECMW_realloc_(void *ptr, size_t size, char *file, int line) {
210  void *ptrnew;
211 
212  ptrnew = realloc(ptr, size);
213 
214  if (size == 0 && ptr != NULL) { /* same as free */
215  if (del_info(ptr)) {
217  "Not found registered memory %p(%s:%d)\n", ptr, file,
218  line);
219  }
220  return NULL;
221  }
222  if (ptr == NULL) { /* same as malloc(size) */
223  if (add_info(ptrnew, size, file, line)) return NULL;
224  } else {
225  if (ptr == ptrnew) {
226  if (change_info(ptr, ptrnew, size, file, line)) {
228  "Not found registered memory %p(%s:%d)\n", ptr, file,
229  line);
230  if (add_info(ptrnew, size, file, line)) return NULL;
231  }
232  } else {
233  if (del_info(ptr)) {
235  "Not found registered memory %p(%s:%d)\n", ptr, file,
236  line);
237  }
238  if (add_info(ptrnew, size, file, line)) goto error;
239  }
240  }
241  if (auto_check) {
242  if (mark_check_memleak()) goto error;
243  }
244  return ptrnew;
245 error:
246  return NULL;
247 }
248 
249 char *HECMW_strdup_(const char *s, char *file, int line) {
250  char *str = NULL;
251  str = strdup(s);
252  if (str == NULL) goto error;
253  if (add_info(str, strlen(str) + 1, file, line)) goto error;
254  if (auto_check) {
255  if (mark_check_memleak()) goto error;
256  }
257  return str;
258 error:
259  free(str);
260  return NULL;
261 }
HECMW_LOG_WARN
#define HECMW_LOG_WARN
Definition: hecmw_log.h:17
hecmw_malloc.h
HECMW_list_meminfo
int HECMW_list_meminfo(FILE *fp)
Definition: hecmw_malloc.c:121
HECMW_check_memleak
int HECMW_check_memleak(void)
Definition: hecmw_malloc.c:138
malloc_info::file
char * file
Definition: hecmw_malloc.c:20
malloc_info::line
int line
Definition: hecmw_malloc.c:21
HECMW_malloc_
void * HECMW_malloc_(size_t size, char *file, int line)
Definition: hecmw_malloc.c:179
HECMW_free_
void HECMW_free_(void *ptr, char *file, int line)
Definition: hecmw_malloc.c:170
HECMW_set_autocheck_memleak
void HECMW_set_autocheck_memleak(int flag)
Definition: hecmw_malloc.c:136
malloc_info::ptr
void * ptr
Definition: hecmw_malloc.c:18
hecmw_config.h
HECMW_realloc_
void * HECMW_realloc_(void *ptr, size_t size, char *file, int line)
Definition: hecmw_malloc.c:209
malloc_info::next
struct malloc_info * next
Definition: hecmw_malloc.c:22
HECMW_strdup_
char * HECMW_strdup_(const char *s, char *file, int line)
Definition: hecmw_malloc.c:249
HECMW_UTIL_E9001
#define HECMW_UTIL_E9001
Definition: hecmw_msgno.h:375
malloc_info
Definition: hecmw_malloc.c:14
HECMW_get_memsize
long HECMW_get_memsize(void)
Definition: hecmw_malloc.c:168
HECMW_print_msg
void HECMW_print_msg(int loglv, int msgno, const char *fmt,...)
Definition: hecmw_util.c:138
HECMW_calloc_
void * HECMW_calloc_(size_t nmemb, size_t size, char *file, int line)
Definition: hecmw_malloc.c:194
NULL
#define NULL
Definition: hecmw_io_nastran.c:30
HECMW_assert
#define HECMW_assert(cond)
Definition: hecmw_util.h:40
malloc_info::size
size_t size
Definition: hecmw_malloc.c:19
hecmw_util.h