APPFS
Advanced practical programming for scientists
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
mshell.c
Go to the documentation of this file.
1 /* $Id: mshell.c,v 1.20 2014/03/03 16:44:15 bzfkocht Exp $ */
2 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3 /* */
4 /* File....: mshell.c */
5 /* Name....: Memory Allocation Shell */
6 /* Author..: Thorsten Koch */
7 /* Copyright by Author, All rights reserved */
8 /* */
9 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10 /*
11  * Copyright (C) 2003-2014 by Thorsten Koch <koch@zib.de>
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public License
15  * as published by the Free Software Foundation; either version 3
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
26  */
27 /*
28  * This is base on the routines from Jim Schimandle,
29  * published in Dr. Dobbs Journal #167 09/90 p.110+.
30  */
31 #include <sys/types.h>
32 #include <unistd.h>
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <assert.h>
37 #include <string.h>
38 
39 #include "lint.h"
40 
41 #define _MSHELL_C_
42 
43 #include "mshell.h"
44 
45 #if !defined(NO_MSHELL)
46 
47 #define ALIGN_SIZE sizeof(double)
48 #define MEMTAG1 0xa55a
49 #define MEMTAG2 0xd88d
50 #define OLDTAG 0xb66b
51 #define ENDTAG 0xc77c
52 
53 typedef struct memnod
54 {
55  unsigned short tag1;
56  unsigned long size;
57  struct memnod* next;
58  struct memnod* prev;
59  char const* file;
60  int line;
61  unsigned short tag2;
62 } MHDR;
63 
64 #define MHDR_NIL ((MHDR*)0)
65 
66 #define HDR_SIZE sizeof(MHDR)
67 #define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE - 1)) \
68  / ALIGN_SIZE) * ALIGN_SIZE)
69 #define CLIENT_2_HDR(a) ((MHDR*)(((char*)(a)) - RESERVE_SIZE))
70 #define HDR_2_CLIENT(a) ((void*)(((char*)(a)) + RESERVE_SIZE))
71 
72 static unsigned long mem_size = 0;
73 static unsigned long mem_maxi = 0;
74 static MHDR* memlist = MHDR_NIL;
75 
76 #define Mem_tag_err(a, b, c, d) mem_tag_err((a), (b), (c), (d), file, line)
77 
78 static size_t mem_alloc_size(
79  size_t size)
80 {
81  size += RESERVE_SIZE + ALIGN_SIZE + ALIGN_SIZE - 1;
82 
83  return((size / ALIGN_SIZE) * ALIGN_SIZE);
84 }
85 
86 static int* mem_endptr(
87  MHDR* p)
88 {
89  size_t offset;
90 
91  assert(p != NULL);
92 
93  offset = ((RESERVE_SIZE + p->size + ALIGN_SIZE - 1) / ALIGN_SIZE)
94  * ALIGN_SIZE;
95 
96  return((int*)((char*)p + offset));
97 }
98 
99 static void mem_add_list(
100  MHDR* p)
101 {
102  assert((p != NULL) && (p->tag1 == MEMTAG1) && (p->tag2 == MEMTAG2));
103 
104  p->next = memlist;
105  p->prev = MHDR_NIL;
106 
107  if (memlist != MHDR_NIL)
108  memlist->prev = p;
109 
110  memlist = p;
111 
112  if (mem_size > mem_maxi)
113  mem_maxi = mem_size;
114 }
115 
116 static void mem_del_list(
117  MHDR *p)
118 {
119  assert((p != NULL) && (p->tag1 == MEMTAG1) && (p->tag2 == MEMTAG2));
120 
121  *mem_endptr(p) = ~ENDTAG;
122  p->tag1 = OLDTAG;
123  p->tag2 = OLDTAG;
124  mem_size -= p->size;
125 
126  if (p->next != MHDR_NIL)
127  p->next->prev = p->prev;
128 
129  if (p->prev != MHDR_NIL)
130  p->prev->next = p->next;
131  else
132  memlist = p->next;
133 }
134 
135 static NORETURN void mem_tag_err(
136  MHDR* p,
137  int typ,
138  const char* file1,
139  const int line1,
140  const char* file2,
141  const int line2)
142 {
143  const char* const errtyp[] = { "pre1", "pre2", "post" };
144 
145  assert((typ >= 0) && (typ <= 2));
146 
147  (void)fprintf(stderr, "Memory tag error (%s) - %lx - %s(%d) at %s(%d)\n",
148  errtyp[typ],
149  (unsigned long)p,
150  file1,
151  line1,
152  file2,
153  line2);
154 
155  mem_display(stderr);
156 
157  abort();
158 }
159 
160 static void mem_valid(
161  MHDR* p,
162  const char* file,
163  const int line)
164 {
165  if (p->tag1 != MEMTAG1)
166  {
167  if (p->tag1 == OLDTAG)
168  Mem_tag_err(p, 0, p->file, p->line);
169 
170  Mem_tag_err(p, 0, "Unknown", 0);
171  }
172  if (p->tag2 != MEMTAG2)
173  {
174  if (p->tag1 == OLDTAG)
175  Mem_tag_err(p, 1, p->file, p->line);
176 
177  Mem_tag_err(p, 1, "Unknown", 0);
178  }
179  if (*mem_endptr(p) != ENDTAG)
180  Mem_tag_err(p, 2, p->file, p->line);
181 }
182 
184  size_t size,
185  const char* file,
186  const int line)
187 {
188  const char* errmsg1 =
189  "mem_malloc(size=%u, file=%s, line=%d): out of memory\n";
190  const char* errmsg2 =
191  "mem_malloc(size=%u, file=%s, line=%d): zero size\n";
192 
193  MHDR* p;
194  size_t alloc_size;
195 
196  if (size == 0)
197  {
198  fprintf(stderr, errmsg2, size, file, line);
199  exit(EXIT_FAILURE);
200  }
201  alloc_size = mem_alloc_size(size);
202 
203  assert(alloc_size > 0);
204 
205  if ((p = malloc(alloc_size)) == MHDR_NIL)
206  {
207  fprintf(stderr, errmsg1, size, file, line);
208  exit(EXIT_FAILURE);
209  }
210  p->tag1 = MEMTAG1;
211  p->tag2 = MEMTAG2;
212  p->size = size;
213  mem_size += size;
214  p->file = file;
215  p->line = line;
216  *mem_endptr(p) = ENDTAG;
217 
218  mem_add_list(p);
219 
220  return(HDR_2_CLIENT(p));
221 }
222 
224  size_t item,
225  size_t size,
226  const char* file,
227  const int line)
228 {
229  const char* errmsg1 =
230  "mem_calloc(item=%u, size=%u, file=%s, line=%d): out of memory\n";
231  const char* errmsg2 =
232  "mem_calloc(item=%u, size=%u, file=%s, line=%d): zero item/size\n";
233 
234  MHDR* p;
235 
236  if (item == 0 || size == 0)
237  {
238  fprintf(stderr, errmsg2, item, size, file, line);
239  exit(EXIT_FAILURE);
240  }
241  if ((p = calloc(mem_alloc_size(size * item), sizeof(char))) == MHDR_NIL)
242  {
243  fprintf(stderr, errmsg1, item, size, file, line);
244  exit(EXIT_FAILURE);
245  }
246  p->tag1 = MEMTAG1;
247  p->tag2 = MEMTAG2;
248  p->size = size * item;
249  mem_size += size * item;
250  p->file = file;
251  p->line = line;
252  *mem_endptr(p) = ENDTAG;
253 
254  mem_add_list(p);
255 
256  return(HDR_2_CLIENT(p));
257 }
258 
260  void* ptr,
261  size_t size,
262  const char* file,
263  const int line)
264 {
265  const char* errmsg1 =
266  "mem_realloc(size=%u, file=%s, line=%d): out of memory\n";
267  const char* errmsg2 =
268  "mem_realloc(file=%s, line=%d): null pointer\n";
269  const char* errmsg3 =
270  "mem_realloc(size=%u, file=%s, line=%d): zero size\n";
271 
272  MHDR* p;
273 
274  if (ptr == NULL)
275  {
276  fprintf(stderr, errmsg2, file, line);
277  exit(EXIT_FAILURE);
278  }
279  p = CLIENT_2_HDR(ptr);
280 
281  mem_valid(p, file, line);
282  mem_del_list(p);
283 
284  if (size == 0)
285  {
286  fprintf(stderr, errmsg3, size, file, line);
287  exit(EXIT_FAILURE);
288  }
289  if ((p = realloc(p, mem_alloc_size(size))) == MHDR_NIL)
290  {
291  fprintf(stderr, errmsg1, size, file, line);
292  exit(EXIT_FAILURE);
293  }
294  p->tag1 = MEMTAG1;
295  p->tag2 = MEMTAG2;
296  p->size = size;
297  mem_size += size;
298  p->file = file;
299  p->line = line;
300  *mem_endptr(p) = ENDTAG;
301 
302  mem_add_list(p);
303 
304  return(HDR_2_CLIENT(p));
305 }
306 
308  const char* str,
309  const char* file,
310  const int line)
311 {
312  const char* errmsg1 = "mem_strdup(file=%s, line=%d): null pointer\n";
313 
314  if (str == NULL)
315  {
316  (void)fprintf(stderr, errmsg1, file, line);
317  exit(EXIT_FAILURE);
318  }
319  return(strcpy(mem_malloc((size_t)(strlen(str) + 1), file, line), str));
320 }
321 
322 void mem_free(
323  void* ptr,
324  const char* file,
325  const int line)
326 {
327  const char *errmsg = "mem_free(file=%s, line=%d): null pointer\n";
328 
329  MHDR* p;
330 
331  if (ptr == NULL)
332  {
333  (void)fprintf(stderr, errmsg, file, line);
334  abort();
335  }
336  p = CLIENT_2_HDR(ptr);
337 
338  mem_valid(p, file, line);
339  mem_del_list(p);
340 
341  free(p);
342 }
343 
345  void* ptr,
346  const char* file,
347  const int line)
348 {
349  const char *errmsg = "mem_checkout(file=%s, line=%d): null pointer\n";
350 
351  MHDR* p;
352 
353  if (ptr == NULL)
354  {
355  (void)fprintf(stderr, errmsg, file, line);
356  abort();
357  }
358  p = CLIENT_2_HDR(ptr);
359 
360  mem_valid(p, file, line);
361  mem_del_list(p);
362 
363  /* Size nicht verringern
364  */
365  mem_size += p->size;
366 }
367 
368 size_t mem_used()
369 {
370  return(mem_size);
371 }
372 
374  FILE* fp)
375 {
376  (void)fprintf(fp, "Maximum amount of memory used = %lu bytes\n",
377  mem_maxi);
378 }
379 
381  FILE* fp)
382 {
383  MHDR* p;
384 
385  (void)fprintf(fp, "\nAddress Size File(Line) - total size %lu\n",
386  mem_size);
387 
388  for(p = memlist; p != MHDR_NIL; p = p->next)
389  {
390  (void)fprintf(fp, "%8lx %6lu %s(%d) %s %s\n",
391  (unsigned long)p,
392  p->size,
393  p->file,
394  p->line,
395  ((p->tag1 != MEMTAG1) || (p->tag2 != MEMTAG2)) ? "Invalid" : "",
396  (*mem_endptr(p) == ENDTAG) ? "ok" : "Clobbered");
397  }
398  mem_maximum(fp);
399 }
400 
402  const void* ptr,
403  const char* file,
404  const int line)
405 {
406  MHDR* p = CLIENT_2_HDR(ptr);
407 
408  mem_valid(p, file, line);
409 }
410 
412  const char* file,
413  const int line)
414 {
415  MHDR* p;
416 
417  for(p = memlist; p != MHDR_NIL; p = p->next)
418  mem_valid(p, file, line);
419 }
420 
421 #else /* NO_MSHELL */
422 
423 void* mem_malloc(
424  size_t size,
425  const char* file,
426  const int line)
427 {
428  const char* errmsg1 =
429  "mem_malloc(size=%u, file=%s, line=%d): out of memory\n";
430 
431  void* p;
432 
433  assert(size > 0);
434 
435  if (NULL == (p = malloc(size)))
436  {
437  fprintf(stderr, errmsg1, size, file, line);
438  exit(EXIT_FAILURE);
439  }
440  return p;
441 }
442 
443 void* mem_calloc(
444  size_t item,
445  size_t size,
446  const char* file,
447  const int line)
448 {
449  const char* errmsg1 =
450  "mem_calloc(item=%u, size=%u, file=%s, line=%d): out of memory\n";
451 
452  void* p;
453 
454  assert(item > 0);
455  assert(size > 0);
456 
457  if (NULL == (p = calloc(item, size)))
458  {
459  fprintf(stderr, errmsg1, item, size, file, line);
460  exit(EXIT_FAILURE);
461  }
462  return p;
463 }
464 
465 void* mem_realloc(
466  void* ptr,
467  size_t size,
468  const char* file,
469  const int line)
470 {
471  const char* errmsg1 =
472  "mem_realloc(size=%u, file=%s, line=%d): out of memory\n";
473 
474  void* p;
475 
476  assert(ptr != NULL);
477  assert(size > 0);
478 
479  if (NULL == (p = realloc(ptr, size)))
480  {
481  fprintf(stderr, errmsg1, size, file, line);
482  exit(EXIT_FAILURE);
483  }
484  return p;
485 }
486 
487 char* mem_strdup(
488  const char* str,
489  const char* file,
490  const int line)
491 {
492  const char* errmsg1 =
493  "mem_strdup(size=%u, file=%s, line=%d): out of memory\n";
494 
495  char* s;
496 
497  assert(str != NULL);
498 
499  if (NULL == (s = strdup(str)))
500  {
501  fprintf(stderr, errmsg1, strlen(str), file, line);
502  exit(EXIT_FAILURE);
503  }
504  return s;
505 }
506 
507 void mem_free(
508  void* ptr,
509  const char* file,
510  const int line)
511 {
512  const char *errmsg = "mem_free(file=%s, line=%d): null pointer\n";
513 
514 #ifndef NDEBUG
515  if (ptr == NULL)
516  {
517  fprintf(stderr, errmsg, file, line);
518  abort();
519  }
520 #endif
521  free(ptr);
522 }
523 
524 #endif /* !NO_MSHELL */
525 
526 /* ------------------------------------------------------------------------- */
527 /* Emacs Local Variables: */
528 /* Emacs mode:c */
529 /* Emacs c-basic-offset:3 */
530 /* Emacs tab-width:8 */
531 /* Emacs indent-tabs-mode:nil */
532 /* Emacs End: */
533 /* ------------------------------------------------------------------------- */
534 
535 
static unsigned long mem_size
Definition: mshell.c:72
char * mem_strdup(const char *str, const char *file, const int line)
Definition: mshell.c:307
static int * mem_endptr(MHDR *p)
Definition: mshell.c:86
#define strdup(a)
Definition: mshell.h:56
#define ALIGN_SIZE
Definition: mshell.c:47
void mem_free(void *ptr, const char *file, const int line)
Definition: mshell.c:322
static NORETURN void mem_tag_err(MHDR *p, int typ, const char *file1, const int line1, const char *file2, const int line2)
Definition: mshell.c:135
static unsigned long mem_maxi
Definition: mshell.c:73
int line
Definition: mshell.c:60
#define malloc(a)
Definition: mshell.h:53
static size_t mem_alloc_size(size_t size)
Definition: mshell.c:78
struct memnod * next
Definition: mshell.c:57
#define MEMTAG1
Definition: mshell.c:48
#define MHDR_NIL
Definition: mshell.c:64
static void mem_del_list(MHDR *p)
Definition: mshell.c:116
#define MEMTAG2
Definition: mshell.c:49
#define Mem_tag_err(a, b, c, d)
Definition: mshell.c:76
struct memnod * prev
Definition: mshell.c:58
struct memnod MHDR
void mem_hide_x(void *ptr, const char *file, const int line)
Definition: mshell.c:344
static MHDR * memlist
Definition: mshell.c:74
static void mem_valid(MHDR *p, const char *file, const int line)
Definition: mshell.c:160
void * mem_malloc(size_t size, const char *file, const int line)
Definition: mshell.c:183
void mem_check_all_x(const char *file, const int line)
Definition: mshell.c:411
#define OLDTAG
Definition: mshell.c:50
static void mem_add_list(MHDR *p)
Definition: mshell.c:99
unsigned short tag2
Definition: mshell.c:61
void mem_maximum(FILE *fp)
Definition: mshell.c:373
size_t mem_used()
Definition: mshell.c:368
void mem_check_x(const void *ptr, const char *file, const int line)
Definition: mshell.c:401
void mem_display(FILE *fp)
Definition: mshell.c:380
#define RESERVE_SIZE
Definition: mshell.c:67
void * mem_calloc(size_t item, size_t size, const char *file, const int line)
Definition: mshell.c:223
#define CLIENT_2_HDR(a)
Definition: mshell.c:69
void * mem_realloc(void *ptr, size_t size, const char *file, const int line)
Definition: mshell.c:259
#define HDR_2_CLIENT(a)
Definition: mshell.c:70
#define ENDTAG
Definition: mshell.c:51
#define calloc(a, b)
Definition: mshell.h:54
#define realloc(a, b)
Definition: mshell.h:55
unsigned short tag1
Definition: mshell.c:55
char const * file
Definition: mshell.c:59
unsigned long size
Definition: mshell.c:56
#define NORETURN
Definition: lint.h:78
Definition: mshell.c:53
#define free(a)
Definition: mshell.h:57