Add some ugly debug code to help track down dangling object references.
git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@2655 4a71c877-e1ca-e34f-864e-861f7616d084master
parent
d668738714
commit
ad9885b14b
44
src/droid.c
44
src/droid.c
|
@ -285,6 +285,50 @@ SDWORD droidDamage(DROID *psDroid, UDWORD damage, UDWORD weaponClass, UDWORD wea
|
|||
return (SDWORD) ((float) actualDamage / originalBody * 100);
|
||||
}
|
||||
|
||||
// Check that psVictimDroid is not referred to by any other object in the game
|
||||
BOOL droidCheckReferences(DROID *psVictimDroid)
|
||||
{
|
||||
int plr, i;
|
||||
|
||||
for (plr = 0; plr < MAX_PLAYERS; plr++)
|
||||
{
|
||||
STRUCTURE *psStruct;
|
||||
DROID *psDroid;
|
||||
|
||||
for (psStruct = apsStructLists[plr]; psStruct != NULL; psStruct = psStruct->psNext)
|
||||
{
|
||||
for (i = 0; i < psStruct->numWeaps; i++)
|
||||
{
|
||||
if ((DROID *)psStruct->psTarget[i] == psVictimDroid)
|
||||
{
|
||||
ASSERT(FALSE, "Illegal reference to droid from %s line %d",
|
||||
psStruct->targetFunc[i], psStruct->targetLine[i]);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (psDroid = apsDroidLists[plr]; psDroid != NULL; psDroid = psDroid->psNext)
|
||||
{
|
||||
for (i = 0; i < psDroid->numWeaps; i++)
|
||||
{
|
||||
if ((DROID *)psDroid->psTarget[i] == psVictimDroid && psVictimDroid != psDroid)
|
||||
{
|
||||
ASSERT(FALSE, "Illegal reference to droid from %s line %d",
|
||||
psDroid->targetFunc[i], psDroid->targetLine[i]);
|
||||
return FALSE;
|
||||
}
|
||||
if ((DROID *)psDroid->psActionTarget[i] == psVictimDroid && psVictimDroid != psDroid)
|
||||
{
|
||||
ASSERT(FALSE, "Illegal action reference to droid from %s line %d",
|
||||
psDroid->actionTargetFunc[i], psDroid->actionTargetLine[i]);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* droidRelease: release all resources associated with a droid -
|
||||
* should only be called by objmem - use vanishDroid preferably
|
||||
*/
|
||||
|
|
39
src/droid.h
39
src/droid.h
|
@ -396,36 +396,69 @@ extern BOOL droidAudioTrackStopped( void *psObj );
|
|||
/*returns TRUE if droid type is one of the Cyborg types*/
|
||||
extern BOOL cyborgDroid(DROID *psDroid);
|
||||
|
||||
// check for illegal references to droid we want to release
|
||||
BOOL droidCheckReferences(DROID *psVictimDroid);
|
||||
|
||||
/** helper functions for future refcount patch **/
|
||||
|
||||
static inline void setDroidTarget(DROID *psDroid, BASE_OBJECT *psNewTarget, UWORD idx)
|
||||
#define setDroidTarget(_psDroid, _psNewTarget, _idx) _setDroidTarget(_psDroid, _psNewTarget, _idx, __LINE__, __FUNCTION__)
|
||||
static inline void _setDroidTarget(DROID *psDroid, BASE_OBJECT *psNewTarget, UWORD idx, int line, const char *func)
|
||||
{
|
||||
psDroid->psTarget[idx] = psNewTarget;
|
||||
ASSERT(psNewTarget == NULL || !psNewTarget->died, "setDroidTarget: Set dead target");
|
||||
#ifdef DEBUG
|
||||
psDroid->targetLine[idx] = line;
|
||||
strlcpy(psDroid->targetFunc[idx], func, MAX_EVENT_NAME_LEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void setDroidActionTarget(DROID *psDroid, BASE_OBJECT *psNewTarget, UWORD idx)
|
||||
#define setDroidActionTarget(_psDroid, _psNewTarget, _idx) _setDroidActionTarget(_psDroid, _psNewTarget, _idx, __LINE__, __FUNCTION__)
|
||||
static inline void _setDroidActionTarget(DROID *psDroid, BASE_OBJECT *psNewTarget, UWORD idx, int line, const char *func)
|
||||
{
|
||||
psDroid->psActionTarget[idx] = psNewTarget;
|
||||
ASSERT(psNewTarget == NULL || !psNewTarget->died, "setDroidActionTarget: Set dead target");
|
||||
#ifdef DEBUG
|
||||
psDroid->actionTargetLine[idx] = line;
|
||||
strlcpy(psDroid->actionTargetFunc[idx], func, MAX_EVENT_NAME_LEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void setDroidBase(DROID *psDroid, STRUCTURE *psNewBase)
|
||||
#define setDroidBase(_psDroid, _psNewTarget) _setDroidBase(_psDroid, _psNewTarget, __LINE__, __FUNCTION__)
|
||||
static inline void _setDroidBase(DROID *psDroid, STRUCTURE *psNewBase, int line, const char *func)
|
||||
{
|
||||
psDroid->psBaseStruct = psNewBase;
|
||||
ASSERT(psNewBase == NULL || !psNewBase->died, "setDroidBase: Set dead target");
|
||||
#ifdef DEBUG
|
||||
psDroid->baseLine = line;
|
||||
strlcpy(psDroid->baseFunc, func, MAX_EVENT_NAME_LEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void setSaveDroidTarget(DROID *psSaveDroid, BASE_OBJECT *psNewTarget, UWORD idx)
|
||||
{
|
||||
psSaveDroid->psTarget[idx] = psNewTarget;
|
||||
#ifdef DEBUG
|
||||
psSaveDroid->targetLine[idx] = 0;
|
||||
strlcpy(psSaveDroid->targetFunc[idx], "savegame", MAX_EVENT_NAME_LEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void setSaveDroidActionTarget(DROID *psSaveDroid, BASE_OBJECT *psNewTarget, UWORD idx)
|
||||
{
|
||||
psSaveDroid->psActionTarget[idx] = psNewTarget;
|
||||
#ifdef DEBUG
|
||||
psSaveDroid->actionTargetLine[idx] = 0;
|
||||
strlcpy(psSaveDroid->actionTargetFunc[idx], "savegame", MAX_EVENT_NAME_LEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void setSaveDroidBase(DROID *psSaveDroid, STRUCTURE *psNewBase)
|
||||
{
|
||||
psSaveDroid->psBaseStruct = psNewBase;
|
||||
#ifdef DEBUG
|
||||
psSaveDroid->baseLine = 0;
|
||||
strlcpy(psSaveDroid->baseFunc, "savegame", MAX_EVENT_NAME_LEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* assert if droid is bad */
|
||||
|
|
|
@ -197,6 +197,15 @@ typedef struct _droid
|
|||
|
||||
BASE_OBJECT *psTarget[DROID_MAXWEAPS]; // Who to shoot at etc
|
||||
BASE_STATS *psTarStats[DROID_MAXWEAPS]; // What to build etc; only first value ever used
|
||||
#ifdef DEBUG
|
||||
// these are to help tracking down dangling pointers
|
||||
char targetFunc[DROID_MAXWEAPS][MAX_EVENT_NAME_LEN];
|
||||
int targetLine[DROID_MAXWEAPS];
|
||||
char actionTargetFunc[DROID_MAXWEAPS][MAX_EVENT_NAME_LEN];
|
||||
int actionTargetLine[DROID_MAXWEAPS];
|
||||
char baseFunc[MAX_EVENT_NAME_LEN];
|
||||
int baseLine;
|
||||
#endif
|
||||
|
||||
// secondary order data
|
||||
UDWORD secondaryOrder;
|
||||
|
|
|
@ -95,11 +95,19 @@ static void objmemDestroy(BASE_OBJECT *psObj)
|
|||
{
|
||||
case OBJ_DROID:
|
||||
debug(LOG_MEMORY, "objmemUpdate: freeing droid at %p", psObj);
|
||||
if (!droidCheckReferences((DROID *)psObj))
|
||||
{
|
||||
return;
|
||||
}
|
||||
droidRelease((DROID *)psObj);
|
||||
break;
|
||||
|
||||
case OBJ_STRUCTURE:
|
||||
debug(LOG_MEMORY, "objmemUpdate: freeing structure at %p", psObj);
|
||||
if (!structureCheckReferences((STRUCTURE *)psObj))
|
||||
{
|
||||
return;
|
||||
}
|
||||
structureRelease((STRUCTURE *)psObj);
|
||||
break;
|
||||
|
||||
|
|
|
@ -8112,3 +8112,53 @@ static void cbNewDroid(STRUCTURE *psFactory, DROID *psDroid)
|
|||
psScrCBNewDroid = NULL;
|
||||
psScrCBNewDroidFact = NULL;
|
||||
}
|
||||
|
||||
// Check that psVictimStruct is not referred to by any other object in the game
|
||||
BOOL structureCheckReferences(STRUCTURE *psVictimStruct)
|
||||
{
|
||||
int plr, i;
|
||||
|
||||
for (plr = 0; plr < MAX_PLAYERS; plr++)
|
||||
{
|
||||
STRUCTURE *psStruct;
|
||||
DROID *psDroid;
|
||||
|
||||
for (psStruct = apsStructLists[plr]; psStruct != NULL; psStruct = psStruct->psNext)
|
||||
{
|
||||
for (i = 0; i < psStruct->numWeaps; i++)
|
||||
{
|
||||
if ((STRUCTURE *)psStruct->psTarget[i] == psVictimStruct && psVictimStruct != psStruct)
|
||||
{
|
||||
ASSERT(FALSE, "Illegal reference to structure from %s line %d",
|
||||
psStruct->targetFunc[i], psStruct->targetLine[i]);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (psDroid = apsDroidLists[plr]; psDroid != NULL; psDroid = psDroid->psNext)
|
||||
{
|
||||
for (i = 0; i < psDroid->numWeaps; i++)
|
||||
{
|
||||
if ((STRUCTURE *)psDroid->psTarget[i] == psVictimStruct)
|
||||
{
|
||||
ASSERT(FALSE, "Illegal reference to structure from %s line %d",
|
||||
psDroid->targetFunc[i], psDroid->targetLine[i]);
|
||||
return FALSE;
|
||||
}
|
||||
if ((STRUCTURE *)psDroid->psActionTarget[i] == psVictimStruct)
|
||||
{
|
||||
ASSERT(FALSE, "Illegal action reference to structure from %s line %d",
|
||||
psDroid->actionTargetFunc[i], psDroid->actionTargetLine[i]);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if ((STRUCTURE *)psDroid->psBaseStruct == psVictimStruct)
|
||||
{
|
||||
ASSERT(FALSE, "Illegal action reference to structure from %s line %d",
|
||||
psDroid->baseFunc, psDroid->baseLine);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -399,10 +399,18 @@ extern BOOL ptInStructure(STRUCTURE *psStruct, UDWORD x, UDWORD y);
|
|||
selected - returns TRUE if valid*/
|
||||
extern BOOL lasSatStructSelected(STRUCTURE *psStruct);
|
||||
|
||||
static inline void setStructureTarget(STRUCTURE *psBuilding, BASE_OBJECT *psNewTarget, UWORD idx)
|
||||
BOOL structureCheckReferences(STRUCTURE *psVictimStruct);
|
||||
|
||||
#define setStructureTarget(_psBuilding, _psNewTarget, _idx) _setStructureTarget(_psBuilding, _psNewTarget, _idx, __LINE__, __FUNCTION__)
|
||||
static inline void _setStructureTarget(STRUCTURE *psBuilding, BASE_OBJECT *psNewTarget, UWORD idx, int line, const char *func)
|
||||
{
|
||||
assert(idx < STRUCT_MAXWEAPS);
|
||||
psBuilding->psTarget[idx] = psNewTarget;
|
||||
ASSERT(psNewTarget == NULL || !psNewTarget->died, "setStructureTarget set dead target");
|
||||
#ifdef DEBUG
|
||||
psBuilding->targetLine[idx] = line;
|
||||
strlcpy(psBuilding->targetFunc[idx], func, MAX_EVENT_NAME_LEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define CHECK_STRUCTURE(object) \
|
||||
|
|
|
@ -335,6 +335,12 @@ typedef struct _structure
|
|||
//Watermelon:more targets
|
||||
BASE_OBJECT *psTarget[STRUCT_MAXWEAPS];
|
||||
|
||||
#ifdef DEBUG
|
||||
// these are to help tracking down dangling pointers
|
||||
char targetFunc[STRUCT_MAXWEAPS][MAX_EVENT_NAME_LEN];
|
||||
int targetLine[STRUCT_MAXWEAPS];
|
||||
#endif
|
||||
|
||||
/* anim data */
|
||||
ANIM_OBJECT *psCurAnim;
|
||||
|
||||
|
|
Loading…
Reference in New Issue