Hi All
After spending more hours trying to identify a problem than I would have liked to I am wondering whether the reason for the problem was bad coding or bad compiling? It failed only with GCC.
This is the line that cost half a day of troubles:
present_task->ulTaskPresentIndex += fnSubroutine(present_task->ulTaskPresentIndex, (void *)present_task); // move to next index
The value present_task->ulTaskPresentIndex is passed to the routine as a value but also a pointer is passed (but declared void) which allows the subroutine to manipulate the same value (present_task->ulTaskPresentIndex) in a particular instance. The return value is used to increment the index with a certain index step.
In the one case where present_task->ulTaskPresentIndex is modified in the subroutine it fails and the following was found to be happening.
- when the subroutine was called present_task->ulTaskPresentIndex was pushed to the stack as passing parameter
- the subroutine modified present_task->ulTaskPresentIndex via the present_task pointer (casted in the subroutine to the same struct pointer type)
- when the subroutine returns it does a pop and also pops back the original present_task->ulTaskPresentIndex value from the stack to the present_task->ulTaskPresentIndex - which is in a register. This means that the change made in the subroutine was cancelled out and the index was then incorrect and written to the 'real' present_task->ulTaskPresentIndex in RAM
The following change worked around this "problem":
int iShift = fnSubroutine(present_task->ulTaskPresentIndex, (void *)present_task);
present_task->ulTaskPresentIndex += iShift;
I can't work out whether it is bad programming or a compiler problem - it didn't make any difference whether optimisation was enabled or not.
Can any compiler experts comment on this and give a rule for programmers to avoid such potential issues?
Regards
Mark