I found an incorrect index was generated in an constant array of structures. I'm curious if it's possible to get the compiler to flag this as a warning or error.
The project creates an array of structures that represent CANOpen Object Dictionary entries. Here are the typedefs.
typedef union _DICT_PTRS { | /* Pointers to objects */ |
long EEAdr;
const unsigned char * pRom;
unsigned char * pRam;
void (* pFunc)(PCHAR pDict);
} DICT_PTRS;
typedef struct _DICTIONARY_OBJECT_TEMPLATE
{
unsigned int index;
unsigned char subindex;
BYTE ctl;
unsigned int len;
DICT_PTRS p;
}DICT_OBJECT_TEMPLATE;
Next the array definition.
const DICT_OBJECT_TEMPLATE manufacturer[] = {
{0x3000,0x00,CONST,1,(long)&UserDictionaryLen},
{0x3000,0x01,RO,2,(long)&ObjectDictionary[BIM_INPUTS_NDX]},
{0x3000,0x02,RO,2,(long)&ObjectDictionary[SMU_INPUTS_NDX]},
{0x3000,0x03,RO,2,(long)&ObjectDictionary[GIM_INPUTS_NDX]},
{0x3000,0x04,RO,2,(long)&ModBusRegisters[OUTBACK_SOURCE_VOLTAGE_NDX]},
...
First of all, there's nothing wrong with the code as is. It's possible to use the functions that work with the array to return the values. In each case the constants that end with NDX are simple #defines that are eventually integers. Looking at the code with the debugger the pointers to the data are correct. Except for the ModBusRegsters[OUTBACK_SOURCE_VOLTAGE_NDX] which is 0.
The problem is that OUTBACK_SOURCE_VOLTAGE_NDX isn't an integer but is (adrChargeControllerBlk+9) and adrChargeControllerBlk is a variable filled in from a MODBUS messages identifying the location of the source voltage value. So the index into the Modbus Registers is dynamic and normally has the value 362.. That doesn't work in a constant array because at compile time the contents of adrChargeControllerBlk are unknown.
In the function that receives the Modbus values it's easy enough to assign the value into a global variable and then use this array entry instead.
{0x3000,0x33,RO,2,(long)&SolarInputVoltage}, | // Filled in if MODBUS active |
Now the constant array has a pointer to the variable SolarInputVoltage and accessing it via the 3000:04 CANOpen Index:Sub-Index returns the correct value. A look with the debugger now shows the correct address in the data structure.
So using the contents of a variable to index a constant array is the problem. The compiler generates a 0 instead of the actual location which it can't know because it doesn't know what's in the variable. All perfectly logical. But shouldn't the compiler complain? I shouldn't have named the index an NDX type. That fooled me into thinking it was an integer a year later when I started using it in this data structure. But still I'd expect an error or at least a warning.
Any suggestions?
Hi,
I got feedback from compiler team.
See below.
+++++++++++++++++++
The value of OUTBACK_SOURCE_VOLTAGE_NDX might be evaluated as a constant at compile time (even if its components do not have the correct / expected content).
This is just a guess, we cannot state from the provided description that this is the case (maybe the code with the complete definition of OUTBACK_SOURCE_VOLTAGE_NDX and of its components might help).
If this is the case (and the OUTBACK_SOURCE_VOLTAGE_NDX can be evaluated as a constant), the compiler does not report any issue (even if the constant evaluated at compile time does not contain the expected value).
+++++++++++++++++++
Have a great day,
Pascal
Freescale Technical Support
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi John,
For my understanding:
- the compiler can not check it.
For the compile there is no error in the code.
The OUTBACK_SOURCE_VOLTAGE_NDX is defined in another module (outside the c file where the manufacturer is defined ) the compiler can not check the address. the address is defined during the link operation.
- the linker doesn't check it too.
The linker is checking memory location, overlap, not missing declarations (functions & variables), ...
Unfortunately I think this type of problem can not be detected by the build tool chain.
I will contact the development team just to have their feedback about that.
Have a great day,
Pascal
Freescale Technical Support
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------