Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions include/extern.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,6 @@

/* ### alloc.c ### */

#if 0
/* routines in alloc.c depend on MONITOR_HEAP and are declared in global.h */
extern long *alloc(unsigned int) NONNULL;
#endif
extern char *fmt_ptr(const void *) NONNULL;
/* moved from hacklib.c to alloc.c so that utility programs have access */
#define FITSint(x) FITSint_(x, __func__, __LINE__)
Expand Down
34 changes: 2 additions & 32 deletions include/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,44 +312,14 @@ typedef uchar nhsym;
* Null; if memory runs out, it calls panic() and does not return at all.
*/

/* dupstr() is unconditional in alloc.c but not used when MONITOR_HEAP
is enabled; some utility programs link with alloc.{o,obj} and need it
if nethack is built with MONITOR_HEAP enabled and they aren't; this
declaration has been moved out of the '#else' below to avoid getting
a complaint from -Wmissing-prototypes when building with MONITOR_HEAP */
extern char *dupstr(const char *) NONNULL NONNULLARG1;
/* same, but return strlen(string) in extra argument */
extern char *dupstr_n(const char *string,
unsigned *lenout) NONNULL NONNULLPTRS;

/*
* MONITOR_HEAP is conditionally used for primitive memory leak debugging.
* When enabled, NH_HEAPLOG (if defined in the environment) is used as the
* name of a log file to create for capturing allocations and releases.
* [The 'heaputil' program to analyze that file isn't included in releases.]
*
* See alloc.c.
*/
#ifdef MONITOR_HEAP
/* plain alloc() is not declared except in alloc.c */
extern long *nhalloc(unsigned int, const char *, int) NONNULL NONNULLARG2;
extern long *nhrealloc(long *, unsigned int, const char *,
int) NONNULL NONNULLARG3;
extern void nhfree(genericptr_t, const char *, int) NONNULLARG2;
extern char *nhdupstr(const char *, const char *, int) NONNULL NONNULLPTRS;
/* this predates C99's __func__; that is trickier to use conditionally
because it is not implemented as a preprocessor macro; MONITOR_HEAP
wouldn't gain much benefit from it anyway so continue to live without it;
if func's caller were accessible, that would be a very different issue */
#define alloc(a) nhalloc(a, __FILE__, (int) __LINE__)
#define re_alloc(a,n) nhrealloc(a, n, __FILE__, (int) __LINE__)
#define free(a) nhfree(a, __FILE__, (int) __LINE__)
#define dupstr(s) nhdupstr(s, __FILE__, (int) __LINE__)
#else /* !MONITOR_HEAP */
/* declare alloc.c's alloc(); allocations made with it use ordinary free() */
extern long *alloc(unsigned int) NONNULL; /* alloc.c */
extern long *re_alloc(long *, unsigned int) NONNULL;
#endif /* ?MONITOR_HEAP */
extern void *alloc(unsigned int) NONNULL; /* alloc.c */
extern void *re_alloc(void *, unsigned int) NONNULL;

/* Used for consistency checks of various data files; declare it here so
that utility programs which include config.h but not hack.h can see it. */
Expand Down
184 changes: 24 additions & 160 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,81 +21,40 @@ extern unsigned FITSuint_(unsigned long long, const char *, int) NONNULLARG2;

char *fmt_ptr(const genericptr) NONNULL;

#ifdef MONITOR_HEAP
#undef alloc
#undef re_alloc
#undef free
extern void free(genericptr_t);
staticfn void heapmon_init(void);

static FILE *heaplog = 0;
static boolean tried_heaplog = FALSE;
#endif

/*
* For historical reasons, nethack's alloc() returns 'long *' rather
* than 'void *' or 'char *'.
*
* Some static analysis complains if it can't deduce that the number
* of bytes being allocated is a multiple of 'sizeof (long)'. It
* recognizes that the following manipulation overcomes that via
* rounding the requested length up to the next long. NetHack doesn't
* make a lot of tiny allocations, so this shouldn't waste much memory
* regardless of whether malloc() does something similar. NetHack
* isn't expected to call alloc(0), but if that happens treat it as
* alloc(sizeof (long)) instead.
*/
#define ForceAlignedLength(LTH) \
do { \
if (!(LTH) || (LTH) % sizeof (long) != 0) \
(LTH) += sizeof (long) - (LTH) % sizeof (long); \
} while (0)

#ifndef MONITOR_HEAP
long *alloc(unsigned int) NONNULL;
long *re_alloc(long *, unsigned int) NONNULL;
#else
/* for #if MONITOR_HEAP, alloc() might return Null but only nhalloc()
should be calling it; nhalloc() never returns Null */
long *alloc(unsigned int);
long *re_alloc(long *, unsigned int);
long *nhalloc(unsigned int, const char *, int) NONNULL;
long *nhrealloc(long *, unsigned int, const char *, int) NONNULL;
#endif
void *alloc(unsigned int) NONNULL;
void *re_alloc(void *, unsigned int) NONNULL;
ATTRNORETURN extern void panic(const char *, ...) PRINTF_F(1, 2) NORETURN;

long *
alloc(unsigned int lth)
void *
alloc(unsigned int bytes)
{
genericptr_t ptr;
void *p;

ForceAlignedLength(lth);
ptr = malloc(lth);
#ifndef MONITOR_HEAP
if (!ptr)
panic("Memory allocation failure; cannot get %u bytes", lth);
#else
/* for #if MONITOR_HEAP, failure is handled in nhalloc() */
#endif
return (long *) ptr;
if (!bytes)
panic("Zero sized allocs not allowed");

p = malloc(bytes);
if (!p)
panic("Memory allocation failure; cannot get %u bytes", bytes);

return p;
}

/* realloc() call that might get substituted by nhrealloc(p,n,file,line) */
long *
re_alloc(long *oldptr, unsigned int newlth)
void *
re_alloc(void *old, unsigned int newlth)
{
long *newptr;
void *p;

ForceAlignedLength(newlth);
newptr = (long *) realloc((genericptr_t) oldptr, (size_t) newlth);
#ifndef MONITOR_HEAP
if (!newlth)
panic("Zero sized reallocs not allowed");

p = realloc(old, (size_t) newlth);
/* "extend to": assume it won't ever fail if asked to shrink */
if (newlth && !newptr)
if (!p)
panic("Memory allocation failure; cannot extend to %u bytes", newlth);
#else
/* for #if MONITOR_HEAP, failure is handled in nhrealloc() */
#endif
return newptr;

return p;
}

#ifdef HAS_PTR_FMT
Expand Down Expand Up @@ -134,102 +93,7 @@ fmt_ptr(const genericptr ptr)
return buf;
}

#ifdef MONITOR_HEAP

/* If ${NH_HEAPLOG} is defined and we can create a file by that name,
then we'll log the allocation and release information to that file. */
staticfn void
heapmon_init(void)
{
char *logname = getenv("NH_HEAPLOG");

if (logname && *logname)
heaplog = fopen(logname, "w");
tried_heaplog = TRUE;
}

long *
nhalloc(unsigned int lth, const char *file, int line)
{
long *ptr = alloc(lth);

if (!tried_heaplog)
heapmon_init();
if (heaplog)
(void) fprintf(heaplog, "+%5u %s %4d %s\n", lth,
fmt_ptr((genericptr_t) ptr), line, file);
/* potential panic in alloc() was deferred til here */
if (!ptr)
panic("Cannot get %u bytes, line %d of %s", lth, line, file);

return ptr;
}

/* re_alloc() with heap logging; we lack access to the old alloc size */
long *
nhrealloc(
long *oldptr,
unsigned int newlth,
const char *file,
int line)
{
long *newptr = re_alloc(oldptr, newlth);

if (!tried_heaplog)
heapmon_init();
if (heaplog) {
char op = '*'; /* assume realloc() will change size of previous
* allocation rather than make a new one */

if (newptr != oldptr) {
/* if oldptr wasn't Null, realloc() freed it */
if (oldptr)
(void) fprintf(heaplog, "%c%5s %s %4d %s\n", '<', "",
fmt_ptr((genericptr_t) oldptr), line, file);
op = '>'; /* new allocation rather than size-change of old one */
}
(void) fprintf(heaplog, "%c%5u %s %4d %s\n", op, newlth,
fmt_ptr((genericptr_t) newptr), line, file);
}
/* potential panic in re_alloc() was deferred til here;
"extend to": assume it won't ever fail if asked to shrink;
even if that assumption happens to be wrong, we lack access to
the old size so can't use alternate phrasing for that case */
if (newlth && !newptr)
panic("Cannot extend to %u bytes, line %d of %s", newlth, line, file);

return newptr;
}

void
nhfree(genericptr_t ptr, const char *file, int line)
{
if (!tried_heaplog)
heapmon_init();
if (heaplog)
(void) fprintf(heaplog, "- %s %4d %s\n",
fmt_ptr((genericptr_t) ptr), line, file);

free(ptr);
}

/* strdup() which uses our alloc() rather than libc's malloc(),
with caller tracking */
char *
nhdupstr(const char *string, const char *file, int line)
{
/* we've got some info about the caller, so use it instead of __func__ */
unsigned len = FITSuint_(strlen(string), file, line);

return strcpy((char *) nhalloc(len + 1, file, line), string);
}
#undef dupstr

#endif /* MONITOR_HEAP */

/* strdup() which uses our alloc() rather than libc's malloc();
not used when MONITOR_HEAP is enabled, but included unconditionally
in case utility programs get built using a different setting for that */
/* strdup() which uses our alloc() rather than libc's malloc(); */
char *
dupstr(const char *string)
{
Expand Down
3 changes: 0 additions & 3 deletions src/mdlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,9 +503,6 @@ static const char *const build_opts[] = {
#ifdef MAIL
"mail daemon",
#endif
#ifdef MONITOR_HEAP
"monitor heap - record memory usage for later analysis",
#endif
#if defined(GNUDOS) || defined(__DJGPP__)
"MSDOS protected mode",
#endif
Expand Down
5 changes: 0 additions & 5 deletions win/X11/winmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,11 +361,6 @@ post_process_tiles(void)
tile_image, 0, 0, 0, 0, /* src, dest top left */
width, height);

#ifdef MONITOR_HEAP
/* if we let XDestroyImage() handle it, our tracking will be off */
if (tile_image->data)
free((genericptr_t) tile_image->data), tile_image->data = 0;
#endif
XDestroyImage(tile_image); /* data bytes free'd also */
tile_image = 0;

Expand Down
2 changes: 0 additions & 2 deletions win/share/gifread.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@
#include "config.h"
#include "tile.h"

#ifndef MONITOR_HEAP
extern long *alloc(unsigned int);
#endif

#define PPM_ASSIGN(p, red, grn, blu) \
do { \
Expand Down
2 changes: 0 additions & 2 deletions win/share/ppmwrite.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
#include "config.h"
#include "tile.h"

#ifndef MONITOR_HEAP
extern long *alloc(unsigned int);
#endif

FILE *ppm_file;

Expand Down
7 changes: 0 additions & 7 deletions win/share/tilemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@
#define Snprintf(str, size, ...) \
nh_snprintf(__func__, __LINE__, str, size, __VA_ARGS__)

#ifdef MONITOR_HEAP
/* with heap monitoring enabled, free(ptr) is a macro which expands to
nhfree(ptr,__FILE__,__LINE__); since tilemap doesn't link with
src/alloc.o it doesn't have access to nhfree(); use actual free */
#undef free
#endif

#define Fprintf (void) fprintf

/*
Expand Down