1

I have a struct declared and set in memory, I have a global constant pointer to this struct and throughout my program I dereference this pointer to access the different parts of the struct. However, there are times when the pointer memory address changes when dereferenced from a specific function.

My struct

typedef struct configData_t
{
    uint8_t version[4];
    inputConfig_t  inputModuleConfig  [MAX_INPUT];
    outputConfig_t outputModuleConfig [MAX_OUTPUT];
    notificationConfig_t notificationConfig [MAX_NOTIFICATIONS];
    functionConfig_t autoFunctionConfig [MAX_FUNCTIONS];
    uint16_t Crc16;
} configData_t;

The constant pointer is declared by setting the memory address of the data (externally loaded and outside of the applications memory)

//Pointer points to memory location on uC (data already in memory)
const configData_t* theConfigData = (configData_t*)0x0460000;

To get a notification from the 'notificationConfig' array I dereference 'theConfigData' by [1]:

const notificationConfig_t *pNotificationConfig = theConfigData->notificationConfig + notificationID;

The following occurs when stepping through the code on the uC:

  1. In function A, get notification from struct by using [1], pointer address is 0x463e18
  2. In function A call function B, dereference the struct using [1] the address changes to 0x463e2a (This is the wrong memory address, 0x12 difference)
  3. Function B finishes and returns to A, dereferencing theConfigData again using [1] gives 0x463e18
  4. Every other function in the program that uses [1] always returns the correct (0x463e18) address.

Function B does not alter 'theConfigData' in any way. In the debuggers memory view, the data in 0x0460000 + sizeOf(configData_t) is not altered in any way.

How is the 'pNotificationConfig' pointer changing address when going from function A to B?

Aaron Thompson
  • 1,849
  • 1
  • 23
  • 31
  • 1
    Is function B in the same compilation unit as function A? (else, there could be allignment issues) – Paul Ogilvie Nov 19 '18 at 09:48
  • 1
    Without relevant code from functions A and B, it is only possible to guess. Odds are some code, somewhere, is molesting a pointer (e.g. dereferencing a NULL, going past the end of an array, doing something with wrong alignment). The offending code could be anywhere - in one of the functions you mention, or somewhere else. Without a [mcve] you can't expect anyone to offer specific answers though. The fact you are initialising a pointer to a fixed value, and later dereferencing it, is also a possible cause of problems. – Peter Nov 19 '18 at 09:51
  • @PaulOgilvie function B is in a separate compilation unit. – Aaron Thompson Nov 19 '18 at 09:52
  • are you sure `notificationID` isn't different in function B ? – Sander De Dycker Nov 19 '18 at 09:54
  • Most likely a bug either in in that function or in the calling code. Other alternatives are classic stack overflow, or perhaps strict aliasing bugs if gcc is involved. – Lundin Nov 19 '18 at 09:54
  • @Peter Function I have reduced function A and function B down to just the code in [1] and I still have the same issue. – Aaron Thompson Nov 19 '18 at 09:54
  • 1
    or alternatively that `sizeof(notificationConfig_t)` is different in function B ? – Sander De Dycker Nov 19 '18 at 09:55
  • @SanderDeDycker Yes, I have tried with a fixed value and not using 'notificationID' at all – Aaron Thompson Nov 19 '18 at 09:56
  • or alternatively that `offsetof(configData_t, notificationConfig)` is different in function B ? – Sander De Dycker Nov 19 '18 at 09:57
  • 1
    @AaronThompson - as I said, the possibilities are endless. One possibility is that some other function (executed before functions A and B) has screwed something up (e.g. overwritten `pNotificationConfig` due to falling off the end of an unrelated array). One "feature" of undefined behaviour is that the code where a symptom occurs (your functions A and B) is not necessarily the code that causes the problem. Repeatedly telling us where the SYMPTOM occurs therefore tells us NOTHING about the cause. A I said, a [mcve] is needed if you expect help that doesn't rely on guess work. – Peter Nov 19 '18 at 10:11
  • Quote " get notification from struct by using [1]" Well, I don't see any code using `[1]` – Support Ukraine Nov 19 '18 at 10:30
  • Are there any interrupts enabled on the uC ? Is your struct declared as `static` ? – luci88filter Nov 19 '18 at 10:32
  • 1
    Most likely in my opinion is an allignment issue in the compilation of modules with function A and function B. Check the compiler flags and packing pragmas. Suggestions of stack overflow or overwriting the pointer as suggested by others is wrong because after function B returns, all other functions use the correct address, as you say. – Paul Ogilvie Nov 19 '18 at 10:41
  • @SanderDeDycker the sizeOf(configData_t) is different in function A and function B, would this indicate an alignment issue? – Aaron Thompson Nov 19 '18 at 11:28
  • 1
    @AaronThompson : it could be a padding issue. It could be an issue with different definitions of `configData_t`. As a first suspect, I would check whether either `MAX_INPUT` and/or `MAX_OUTPUT` are different in the B compilation unit (at the point of he `configData_t` definition). If they're the same, check whether the `configData_t` definition differs in another way. If there's no difference, then check compiler flags (specifically wrt. struct packing). – Sander De Dycker Nov 19 '18 at 11:48
  • Thank you @SanderDeDycker and @PaulOgilvie, it was an alignment issue between the different compilation units. Adding `__attribute__((__packed__))` to the `typedef struct` has solved the problem – Aaron Thompson Nov 19 '18 at 11:55

1 Answers1

1

You need to make sure that :

  • the definition of configData_t is exactly the same in both the function A and function B compilation units
  • the struct padding of configData_t is exactly the same for both the function A and function B compilation units

Red flags of the above for your specific issue would be eg. :

  • sizeof(configData_t) is different
  • offsetof(configData_t, notificationConfig) is different
  • sizeof(notificationConfig_t) is different

If one or more of these red flags are raised (and in a comment, you confirm that), you need to determine which of the two earlier options causes it :

  • a difference in definition can be caught by verifying the source code :
    • make sure the same struct definitions are used throughout the code (typically with the use of an include file)
    • make sure supporting compile time values are the same (eg. array dimensions MAX_INPUT, MAX_OUTPUT, ... in your case)
  • a difference in padding can be caused by the use of different compilers and/or different compiler flags - refer to your compiler's documentation for details (specifically wrt. struct padding/packing)
Sander De Dycker
  • 16,053
  • 1
  • 35
  • 40