1 /* NetHack 3.7	alloc.c	$NHDT-Date: 1596498147 2020/08/03 23:42:27 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.18 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2012. */
4 /* NetHack may be freely redistributed.  See license for details. */
5 
6 /* to get the malloc() prototype from system.h */
7 #define ALLOC_C /* comment line for pre-compiled headers */
8 /* since this file is also used in auxiliary programs, don't include all the
9    function declarations for all of nethack */
10 #define EXTERN_H /* comment line for pre-compiled headers */
11 #include "config.h"
12 
13 char *fmt_ptr(const genericptr);
14 
15 #ifdef MONITOR_HEAP
16 #undef alloc
17 #undef free
18 extern void free(genericptr_t);
19 static void heapmon_init(void);
20 
21 static FILE *heaplog = 0;
22 static boolean tried_heaplog = FALSE;
23 #endif
24 
25 long *alloc(unsigned int);
26 extern void panic(const char *, ...);
27 
28 long *
alloc(unsigned int lth)29 alloc(unsigned int lth)
30 {
31 #ifdef LINT
32     /*
33      * a ridiculous definition, suppressing
34      *  "possible pointer alignment problem" for (long *) malloc()
35      * from lint
36      */
37     long dummy = ftell(stderr);
38 
39     if (lth)
40         dummy = 0; /* make sure arg is used */
41     return &dummy;
42 #else
43     register genericptr_t ptr;
44 
45     ptr = malloc(lth);
46 #ifndef MONITOR_HEAP
47     if (!ptr)
48         panic("Memory allocation failure; cannot get %u bytes", lth);
49 #endif
50     return (long *) ptr;
51 #endif
52 }
53 
54 #ifdef HAS_PTR_FMT
55 #define PTR_FMT "%p"
56 #define PTR_TYP genericptr_t
57 #else
58 #define PTR_FMT "%06lx"
59 #define PTR_TYP unsigned long
60 #endif
61 
62 /* A small pool of static formatting buffers.
63  * PTRBUFSIZ:  We assume that pointers will be formatted as integers in
64  * hexadecimal, requiring at least 16+1 characters for each buffer to handle
65  * 64-bit systems, but the standard doesn't mandate that encoding and an
66  * implementation could do something different for %p, so we make some
67  * extra room.
68  * PTRBUFCNT:  Number of formatted values which can be in use at the same
69  * time.  To have more, callers need to make copies of them as they go.
70  */
71 #define PTRBUFCNT 4
72 #define PTRBUFSIZ 32
73 static char ptrbuf[PTRBUFCNT][PTRBUFSIZ];
74 static int ptrbufidx = 0;
75 
76 /* format a pointer for display purposes; returns a static buffer */
77 char *
fmt_ptr(const genericptr ptr)78 fmt_ptr(const genericptr ptr)
79 {
80     char *buf;
81 
82     buf = ptrbuf[ptrbufidx];
83     if (++ptrbufidx >= PTRBUFCNT)
84         ptrbufidx = 0;
85 
86     Sprintf(buf, PTR_FMT, (PTR_TYP) ptr);
87     return buf;
88 }
89 
90 #ifdef MONITOR_HEAP
91 
92 /* If ${NH_HEAPLOG} is defined and we can create a file by that name,
93    then we'll log the allocation and release information to that file. */
94 static void
heapmon_init(void)95 heapmon_init(void)
96 {
97     char *logname = getenv("NH_HEAPLOG");
98 
99     if (logname && *logname)
100         heaplog = fopen(logname, "w");
101     tried_heaplog = TRUE;
102 }
103 
104 long *
nhalloc(unsigned int lth,const char * file,int line)105 nhalloc(unsigned int lth, const char *file, int line)
106 {
107     long *ptr = alloc(lth);
108 
109     if (!tried_heaplog)
110         heapmon_init();
111     if (heaplog)
112         (void) fprintf(heaplog, "+%5u %s %4d %s\n", lth,
113                        fmt_ptr((genericptr_t) ptr), line, file);
114     /* potential panic in alloc() was deferred til here */
115     if (!ptr)
116         panic("Cannot get %u bytes, line %d of %s", lth, line, file);
117 
118     return ptr;
119 }
120 
121 void
nhfree(genericptr_t ptr,const char * file,int line)122 nhfree(genericptr_t ptr, const char *file, int line)
123 {
124     if (!tried_heaplog)
125         heapmon_init();
126     if (heaplog)
127         (void) fprintf(heaplog, "-      %s %4d %s\n",
128                        fmt_ptr((genericptr_t) ptr), line, file);
129 
130     free(ptr);
131 }
132 
133 /* strdup() which uses our alloc() rather than libc's malloc(),
134    with caller tracking */
135 char *
nhdupstr(const char * string,const char * file,int line)136 nhdupstr(const char *string, const char *file, int line)
137 {
138     return strcpy((char *) nhalloc(strlen(string) + 1, file, line), string);
139 }
140 #undef dupstr
141 
142 #endif /* MONITOR_HEAP */
143 
144 /* strdup() which uses our alloc() rather than libc's malloc();
145    not used when MONITOR_HEAP is enabled, but included unconditionally
146    in case utility programs get built using a different setting for that */
147 char *
dupstr(const char * string)148 dupstr(const char *string)
149 {
150     return strcpy((char *) alloc(strlen(string) + 1), string);
151 }
152 
153 /*alloc.c*/
154