0

I have been asked to finish some code someone else started, and I am completely confused on how to copy a U32 value inside an struct. These are the relevant parts of the various structs; note that I am trimming a lot because those are some seriously huge structs:

typedef struct AttackerList {
    U32 count;
} AttackerList;

typedef struct AggroVars {
    AttackerList attackerList;
}

typedef struct Player {
    U32 aiAttackers;
}

Now, in the function I am trying to modify:

void attackTarget(Player* target) {
   AggroVars* aiTarget;
   // Tons of code here.
   aiTarget->attackerList.count++;
   target->aiAttackers = aiTarget->attackerList.count;
   // Tons more code here.
}

That last line is the one that is causing me all sorts of grief. It does work, I can see in the debug output how many critters are attacking the player; but it causes a crash whenever the AI loses interest in the target. I know this has something to do with pointers, but sprinkling asterisks on the code results in either "invalid indirection" or "differs in levels of indirection". I am pretty much stumped on how to retrieve just the value of aiTarget->attackerList.count without any weird pointer stuff.

  • " ** sprinkling asterisks on the code** " is *not* an effective debugging technique!! – Moo-Juice Jan 10 '14 at 11:33
  • It's pretty hard to debug an issue about pointers without relevant code! You know, the _working example_ stuff... (BTW if your function has **two tons of code**, too long to be posted...I'd refactor little bit...) – Adriano Repetti Jan 10 '14 at 11:33
  • 1
    check if variables 'target' or 'aiTarget' are NULL before accessing the value. This might help you to get the answer. – Srini Jan 10 '14 at 11:37
  • I was hoping that it wouldn't need to copy a lot of the function because it's honestly huge, and calling it "working" is being too benign. What would you need, everywhere aiTarget is touched? – calmira Jan 10 '14 at 11:39
  • Maybe but error can even be in another place and perfectly valid code may fail because of data corruption (made in another unseen function). I'd suggest to first add as much ASSERT as you can to validate all preconditions. To split that huge function in smaller functions will help you on this. – Adriano Repetti Jan 10 '14 at 12:02
  • I am absolutely dreading the idea of refactoring or rewriting that function. It pulls data from a dozen different places to determine which target should that particular AI attack, and I honestly don't understand most of it. I was hoping it would be something obvious that I was missing (I've been staring at this function for the last 9 hours), so it'd probably be less stressful to remove aiAttackers as a feature and do a much dumber check, like how many hostile entities are at a certain distance of the player. – calmira Jan 10 '14 at 12:28

2 Answers2

0

Instead of "sprinkling asterisks" I suggest sprinkling assertions in the tons of code we don't see after these variables were initialized or modified:

#include <assert.h>

...
assert (target != NULL);
assert (aiTarget != NULL);

This might point you in the right direction.

Jens
  • 69,818
  • 15
  • 125
  • 179
  • There's an if(target) very near the top of the function (basically the whole function is wrapped in that if) and an if(aiTarget) a few dozen lines above the quoted bits. I am **pretty sure** both of them are initialized and hold data at the time those two lines are called. I'll add the asserts anyway just in case. – calmira Jan 10 '14 at 12:23
0

you need first to allocate memory for each structure so in your code make below changes

void attackTarget(Player* target) 
{
   AggroVars* aiTarget = malloc(sizeof(AggroVars));

   aiTarget->attackerList.count++;

   target->aiAttackers = aiTarget->attackerList.count;

}
Jayesh Bhoi
  • 24,694
  • 15
  • 58
  • 73