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-861f7616d084
master
Per Inge Mathisen 2007-10-28 21:47:52 +00:00
parent d668738714
commit ad9885b14b
7 changed files with 162 additions and 4 deletions

View File

@ -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
*/

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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) \

View File

@ -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;