Plug memory leaks in mission execution code

Mission execution first builds lists of eligible units, one list per
country.  These lists are passed to perform_mission() one by one,
where they get freed.

Bugs:

* unit_interdict() didn't pass the list for the submarine's owner, but
  build_mission_list_type() built one.  Any submarine movement within
  own submarine interdiction mission op areas leaked memory.

* dosupport() passed only lists for countries that actually support
  (ally at war with victim), but build_mission_list_type() built lists
  for all countries hostile to the victim.  Ground combat within
  support mission op areas countries that are hostile to one of the
  party without actually supporting the other leaked memory.

* perform_mission() failed to free missiles targeting units.

Fixing the latter is straightforward.

Fix the first two by deciding whether a country acts on a mission
trigger before building any lists, in ground_interdict(),
unit_interdict(), dosupport().  Remove the code dealing with that from
build_mission_list_type() and the loops around perform_mission().
This commit is contained in:
Markus Armbruster 2011-01-31 07:56:44 +01:00
parent 6a35432346
commit 7374002fd7

View file

@ -63,9 +63,11 @@ struct airport {
static void add_airport(struct emp_qelem *, coord, coord); static void add_airport(struct emp_qelem *, coord, coord);
static int air_damage(struct emp_qelem *, coord, coord, int, natid, static int air_damage(struct emp_qelem *, coord, coord, int, natid,
char *, int); char *, int);
static void build_mission_list(struct genlist *, coord, coord, int, natid); static void build_mission_list(struct genlist[],
static void build_mission_list_type(struct genlist *, coord, coord, int, unsigned char[], unsigned char[],
int, natid); coord, coord, int);
static void build_mission_list_type(struct genlist[], unsigned char[],
coord, coord, int, int);
static void divide(struct emp_qelem *, struct emp_qelem *, coord, coord); static void divide(struct emp_qelem *, struct emp_qelem *, coord, coord);
static int dosupport(coord, coord, natid, natid, int); static int dosupport(coord, coord, natid, natid, int);
static int find_airport(struct emp_qelem *, coord, coord); static int find_airport(struct emp_qelem *, coord, coord);
@ -96,20 +98,20 @@ int
ground_interdict(coord x, coord y, natid victim, char *s) ground_interdict(coord x, coord y, natid victim, char *s)
{ {
int cn; int cn;
int dam = 0, newdam, rel; int dam = 0, newdam;
unsigned char act[MAXNOC];
struct genlist mi[MAXNOC]; struct genlist mi[MAXNOC];
memset(mi, 0, sizeof(mi)); memset(mi, 0, sizeof(mi));
for (cn = 1; cn < MAXNOC; cn++) act[0] = 0;
for (cn = 1; cn < MAXNOC; cn++) {
act[cn] = getrel(getnatp(cn), victim) <= HOSTILE;
emp_initque((struct emp_qelem *)&mi[cn]); emp_initque((struct emp_qelem *)&mi[cn]);
}
build_mission_list(mi, x, y, MI_INTERDICT, victim); build_mission_list(mi, act, act, x, y, MI_INTERDICT);
for (cn = 1; cn < MAXNOC; cn++) { for (cn = 1; cn < MAXNOC; cn++) {
rel = getrel(getnatp(cn), victim);
if (rel > HOSTILE)
continue;
if (QEMPTY(&mi[cn].queue)) if (QEMPTY(&mi[cn].queue))
continue; continue;
@ -177,25 +179,24 @@ int
unit_interdict(coord x, coord y, natid victim, char *s, int hardtarget, unit_interdict(coord x, coord y, natid victim, char *s, int hardtarget,
int mission) int mission)
{ {
int cn, newdam, osubs; int cn, rel, newdam, osubs;
int dam = -1; int dam = -1;
unsigned char plane_act[MAXNOC], other_act[MAXNOC];
struct genlist mi[MAXNOC]; struct genlist mi[MAXNOC];
memset(mi, 0, sizeof(mi)); memset(mi, 0, sizeof(mi));
for (cn = 1; cn < MAXNOC; cn++) other_act[0] = plane_act[0] = 0;
for (cn = 1; cn < MAXNOC; cn++) {
rel = getrel(getnatp(cn), victim);
other_act[cn] = rel <= HOSTILE;
plane_act[cn] = mission == MI_SINTERDICT
? cn != victim && rel <= NEUTRAL : other_act[cn];
emp_initque((struct emp_qelem *)&mi[cn]); emp_initque((struct emp_qelem *)&mi[cn]);
}
build_mission_list(mi, x, y, mission, victim); build_mission_list(mi, other_act, plane_act, x, y, mission);
for (cn = 1; cn < MAXNOC; cn++) { for (cn = 1; cn < MAXNOC; cn++) {
if (cn == victim)
continue;
if (mission == MI_SINTERDICT) {
if (getrel(getnatp(cn), victim) >= FRIENDLY)
continue;
} else if (getrel(getnatp(cn), victim) > HOSTILE)
continue;
if (QEMPTY(&mi[cn].queue)) if (QEMPTY(&mi[cn].queue))
continue; continue;
@ -234,25 +235,24 @@ static int
dosupport(coord x, coord y, natid victim, natid actee, int mission) dosupport(coord x, coord y, natid victim, natid actee, int mission)
{ {
int cn; int cn;
unsigned char act[MAXNOC];
struct genlist mi[MAXNOC]; struct genlist mi[MAXNOC];
int rel, newdam; int newdam;
int dam = 0; int dam = 0;
memset(mi, 0, sizeof(mi)); memset(mi, 0, sizeof(mi));
for (cn = 1; cn < MAXNOC; cn++) act[0] = 0;
for (cn = 1; cn < MAXNOC; cn++) {
act[cn] = (cn == actee
|| (getrel(getnatp(cn), actee) == ALLIED
&& getrel(getnatp(cn), victim) == AT_WAR));
emp_initque((struct emp_qelem *)&mi[cn]); emp_initque((struct emp_qelem *)&mi[cn]);
}
build_mission_list(mi, x, y, MI_SUPPORT, victim); build_mission_list(mi, act, act, x, y, MI_SUPPORT);
build_mission_list(mi, x, y, mission, victim); build_mission_list(mi, act, act, x, y, mission);
for (cn = 1; cn < MAXNOC; cn++) { for (cn = 1; cn < MAXNOC; cn++) {
rel = getrel(getnatp(cn), actee);
if ((cn != actee) && (rel != ALLIED))
continue;
rel = getrel(getnatp(cn), victim);
if ((cn != actee) && (rel != AT_WAR))
continue;
if (QEMPTY(&mi[cn].queue)) if (QEMPTY(&mi[cn].queue))
continue; continue;
@ -265,29 +265,29 @@ dosupport(coord x, coord y, natid victim, natid actee, int mission)
} }
static void static void
build_mission_list(struct genlist *mi, coord x, coord y, int mission, build_mission_list(struct genlist mi[],
natid victim) unsigned char other_act[], unsigned char plane_act[],
coord x, coord y, int mission)
{ {
build_mission_list_type(mi, x, y, mission, EF_LAND, victim); build_mission_list_type(mi, other_act, x, y, mission, EF_LAND);
build_mission_list_type(mi, x, y, mission, EF_SHIP, victim); build_mission_list_type(mi, other_act, x, y, mission, EF_SHIP);
build_mission_list_type(mi, x, y, mission, EF_PLANE, victim); build_mission_list_type(mi, plane_act, x, y, mission, EF_PLANE);
} }
static void static void
build_mission_list_type(struct genlist *mi, coord x, coord y, int mission, build_mission_list_type(struct genlist mi[], unsigned char act[],
int type, natid victim) coord x, coord y, int mission, int type)
{ {
struct nstr_item ni; struct nstr_item ni;
struct genlist *glp; struct genlist *glp;
struct empobj *gp; struct empobj *gp;
union empobj_storage item; union empobj_storage item;
int relat;
snxtitem_all(&ni, type); snxtitem_all(&ni, type);
while (nxtitem(&ni, &item)) { while (nxtitem(&ni, &item)) {
gp = (struct empobj *)&item; gp = (struct empobj *)&item;
if (gp->own == 0) if (!act[gp->own])
continue; continue;
if (gp->mobil < 1) if (gp->mobil < 1)
@ -300,15 +300,6 @@ build_mission_list_type(struct genlist *mi, coord x, coord y, int mission,
(gp->mission != MI_INTERDICT)) (gp->mission != MI_INTERDICT))
continue; continue;
relat = getrel(getnatp(gp->own), victim);
if (mission == MI_SINTERDICT) {
if (relat >= FRIENDLY)
continue;
else if (type != EF_PLANE && relat > HOSTILE)
continue;
} else if (relat > HOSTILE)
continue;
if (!in_oparea(gp, x, y)) if (!in_oparea(gp, x, y))
continue; continue;
@ -371,11 +362,11 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
targeting_ships); targeting_ships);
} else if (glp->thing->ef_type == EF_PLANE) { } else if (glp->thing->ef_type == EF_PLANE) {
pcp = &plchr[glp->thing->type]; pcp = &plchr[glp->thing->type];
if (pcp->pl_flags & P_M) if ((pcp->pl_flags & P_M)
/* units have their own missile interdiction */ && (hardtarget != SECT_HARDTARGET
if (hardtarget != SECT_HARDTARGET || pcp->pl_flags & P_MAR) || (pcp->pl_flags & P_MAR)))
continue; ; /* units have their own missile interdiction */
else {
/* save planes for later */ /* save planes for later */
plp = malloc(sizeof(struct plist)); plp = malloc(sizeof(struct plist));
@ -386,6 +377,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
emp_insque(&plp->queue, &missiles); emp_insque(&plp->queue, &missiles);
else else
emp_insque(&plp->queue, &bombers); emp_insque(&plp->queue, &bombers);
}
} else { } else {
CANT_REACH(); CANT_REACH();
break; break;