fix memory leak: obj->oextra->omonst->mextra

The memory leak (monst->mextra->edog, monst->mextra->mname,
monst->mextra for some monster were not released) I noticed recently
was due to recording a pet's full monster attributes with its corpse.
During save and restore, obj->oextra->omonst was being treated as a
full-fledged monster so worked as intended, but when freed, omonst
was treated as a black box and its mextra details weren't handled.
This commit is contained in:
PatR
2015-11-13 20:39:10 -08:00
parent 24099c50b2
commit 95772261dc
4 changed files with 41 additions and 22 deletions
+3 -2
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1447124656 2015/11/10 03:04:16 $ $NHDT-Branch: master $:$NHDT-Revision: 1.515 $ */ /* NetHack 3.6 extern.h $NHDT-Date: 1447475941 2015/11/14 04:39:01 $ $NHDT-Branch: master $:$NHDT-Revision: 1.516 $ */
/* Copyright (c) Steve Creps, 1988. */ /* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1070,6 +1070,7 @@ E int FDECL(monhp_per_lvl, (struct monst *));
E void FDECL(newmonhp, (struct monst *, int)); E void FDECL(newmonhp, (struct monst *, int));
E struct mextra *NDECL(newmextra); E struct mextra *NDECL(newmextra);
E void FDECL(copy_mextra, (struct monst *, struct monst *)); E void FDECL(copy_mextra, (struct monst *, struct monst *));
E void FDECL(dealloc_mextra, (struct monst *));
E struct monst *FDECL(makemon, (struct permonst *, int, int, int)); E struct monst *FDECL(makemon, (struct permonst *, int, int, int));
E boolean FDECL(create_critters, (int, struct permonst *, BOOLEAN_P)); E boolean FDECL(create_critters, (int, struct permonst *, BOOLEAN_P));
E struct permonst *NDECL(rndmonst); E struct permonst *NDECL(rndmonst);
@@ -1203,7 +1204,7 @@ E const char *FDECL(waterbody_name, (XCHAR_P, XCHAR_P));
E struct oextra *NDECL(newoextra); E struct oextra *NDECL(newoextra);
E void FDECL(copy_oextra, (struct obj *, struct obj *)); E void FDECL(copy_oextra, (struct obj *, struct obj *));
E void FDECL(dealloc_oextra, (struct oextra *)); E void FDECL(dealloc_oextra, (struct obj *));
E void FDECL(newomonst, (struct obj *)); E void FDECL(newomonst, (struct obj *));
E void FDECL(free_omonst, (struct obj *)); E void FDECL(free_omonst, (struct obj *));
E void FDECL(newomid, (struct obj *)); E void FDECL(newomid, (struct obj *));
+26 -10
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 mkobj.c $NHDT-Date: 1446892448 2015/11/07 10:34:08 $ $NHDT-Branch: master $:$NHDT-Revision: 1.112 $ */ /* NetHack 3.6 mkobj.c $NHDT-Date: 1447475943 2015/11/14 04:39:03 $ $NHDT-Branch: master $:$NHDT-Revision: 1.113 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -79,21 +79,25 @@ newoextra()
} }
void void
dealloc_oextra(x) dealloc_oextra(o)
struct oextra *x; struct obj *o;
{ {
struct oextra *x = o->oextra;
if (x) { if (x) {
if (x->oname) if (x->oname)
free((genericptr_t) x->oname); free((genericptr_t) x->oname);
if (x->omonst) if (x->omonst)
free((genericptr_t) x->omonst); free_omonst(o); /* 'o' rather than 'x' */
if (x->omid) if (x->omid)
free((genericptr_t) x->omid); free((genericptr_t) x->omid);
if (x->olong) if (x->olong)
free((genericptr_t) x->olong); free((genericptr_t) x->olong);
if (x->omailcmd) if (x->omailcmd)
free((genericptr_t) x->omailcmd); free((genericptr_t) x->omailcmd);
free((genericptr_t) x); free((genericptr_t) x);
o->oextra = (struct oextra *) 0;
} }
} }
@@ -104,8 +108,13 @@ struct obj *otmp;
if (!otmp->oextra) if (!otmp->oextra)
otmp->oextra = newoextra(); otmp->oextra = newoextra();
if (!OMONST(otmp)) { if (!OMONST(otmp)) {
OMONST(otmp) = (struct monst *) alloc(sizeof (struct monst)); struct monst *m = newmonst();
(void) memset((genericptr_t) OMONST(otmp), 0, sizeof (struct monst));
/* newmonst() allocates memory but doesn't initialize anything */
(void) memset((genericptr_t) m, 0, sizeof (struct monst));
m->mextra = (struct mextra *) 0;
m->nmon = (struct monst *) 0;
OMONST(otmp) = m;
} }
} }
@@ -113,9 +122,15 @@ void
free_omonst(otmp) free_omonst(otmp)
struct obj *otmp; struct obj *otmp;
{ {
if (otmp->oextra && OMONST(otmp)) { if (otmp->oextra) {
free((genericptr_t) OMONST(otmp)); struct monst *m = OMONST(otmp);
OMONST(otmp) = (struct monst *) 0;
if (m) {
if (m->mextra)
dealloc_mextra(m);
free((genericptr_t) m);
OMONST(otmp) = (struct monst *) 0;
}
} }
} }
@@ -1511,6 +1526,7 @@ struct monst *mtmp;
newomonst(obj); newomonst(obj);
if (has_omonst(obj)) { if (has_omonst(obj)) {
struct monst *mtmp2 = OMONST(obj); struct monst *mtmp2 = OMONST(obj);
*mtmp2 = *mtmp; *mtmp2 = *mtmp;
mtmp2->mextra = (struct mextra *) 0; mtmp2->mextra = (struct mextra *) 0;
if (mtmp->data) if (mtmp->data)
@@ -2053,7 +2069,7 @@ struct obj *obj;
kickedobj = 0; kickedobj = 0;
if (obj->oextra) if (obj->oextra)
dealloc_oextra(obj->oextra); dealloc_oextra(obj);
free((genericptr_t) obj); free((genericptr_t) obj);
} }
+9 -6
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 mon.c $NHDT-Date: 1446458009 2015/11/02 09:53:29 $ $NHDT-Branch: master $:$NHDT-Revision: 1.194 $ */ /* NetHack 3.6 mon.c $NHDT-Date: 1447475944 2015/11/14 04:39:04 $ $NHDT-Branch: master $:$NHDT-Revision: 1.196 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -18,7 +18,6 @@ STATIC_DCL long FDECL(mm_aggression, (struct monst *, struct monst *));
STATIC_DCL long FDECL(mm_displacement, (struct monst *, struct monst *)); STATIC_DCL long FDECL(mm_displacement, (struct monst *, struct monst *));
STATIC_DCL int NDECL(pick_animal); STATIC_DCL int NDECL(pick_animal);
STATIC_DCL void FDECL(kill_eggs, (struct obj *)); STATIC_DCL void FDECL(kill_eggs, (struct obj *));
STATIC_DCL void FDECL(dealloc_mextra, (struct mextra *));
STATIC_DCL int FDECL(pickvampshape, (struct monst *)); STATIC_DCL int FDECL(pickvampshape, (struct monst *));
STATIC_DCL boolean FDECL(isspecmon, (struct monst *)); STATIC_DCL boolean FDECL(isspecmon, (struct monst *));
STATIC_DCL boolean FDECL(validspecmon, (struct monst *, int)); STATIC_DCL boolean FDECL(validspecmon, (struct monst *, int));
@@ -1597,10 +1596,12 @@ struct monst *mtmp2, *mtmp1;
MCORPSENM(mtmp2) = MCORPSENM(mtmp1); MCORPSENM(mtmp2) = MCORPSENM(mtmp1);
} }
STATIC_OVL void void
dealloc_mextra(x) dealloc_mextra(m)
struct mextra *x; struct monst *m;
{ {
struct mextra *x = m->mextra;
if (x) { if (x) {
if (x->mname) if (x->mname)
free((genericptr_t) x->mname); free((genericptr_t) x->mname);
@@ -1615,7 +1616,9 @@ struct mextra *x;
if (x->edog) if (x->edog)
free((genericptr_t) x->edog); free((genericptr_t) x->edog);
/* [no action needed for x->mcorpsenm] */ /* [no action needed for x->mcorpsenm] */
free((genericptr_t) x); free((genericptr_t) x);
m->mextra = (struct mextra *) 0;
} }
} }
@@ -1626,7 +1629,7 @@ struct monst *mon;
if (mon->nmon) if (mon->nmon)
panic("dealloc_monst with nmon"); panic("dealloc_monst with nmon");
if (mon->mextra) if (mon->mextra)
dealloc_mextra(mon->mextra); dealloc_mextra(mon);
free((genericptr_t) mon); free((genericptr_t) mon);
} }
+3 -4
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 zap.c $NHDT-Date: 1446887542 2015/11/07 09:12:22 $ $NHDT-Branch: master $:$NHDT-Revision: 1.233 $ */ /* NetHack 3.6 zap.c $NHDT-Date: 1447475947 2015/11/14 04:39:07 $ $NHDT-Branch: master $:$NHDT-Revision: 1.235 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -4462,9 +4462,8 @@ register struct obj *obj; /* no texts here! */
obj->owt = weight(obj); obj->owt = weight(obj);
obj->dknown = obj->bknown = obj->rknown = 0; obj->dknown = obj->bknown = obj->rknown = 0;
obj->known = objects[obj->otyp].oc_uses_known ? 0 : 1; obj->known = objects[obj->otyp].oc_uses_known ? 0 : 1;
if (obj->oextra) dealloc_oextra(obj);
dealloc_oextra(obj->oextra);
obj->oextra = (struct oextra *) 0;
if (obj->where == OBJ_FLOOR) { if (obj->where == OBJ_FLOOR) {
obj_extract_self(obj); /* move rocks back on top */ obj_extract_self(obj); /* move rocks back on top */
place_object(obj, obj->ox, obj->oy); place_object(obj, obj->ox, obj->oy);