warning "array subscript 2 is outside array bounds of ..."

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

warning "array subscript 2 is outside array bounds of ..."

Jump to solution
2,745 Views
arnogir
Senior Contributor II

Hello,

 

I'm using MCUXpresso (v11.6) on MKL33Z256 and I get a warning at compile time:

"array subscript 2 is outside array bounds of 'uint32_t[1]' {aka 'unsigned int[1]'} [-Warray-bounds]"

I try many solution but not working.

Bellow is my simplified code :

 

 

static boolean MyFunc(const uint8_t* FlashAddressPtr)
{  
  const uint8_t Header[] = {0xF1, 0xF1, 0x01, 0x00};  /* Magic Code + the number of Certificate file... */
  uint32_t      ListSize;
  uint16_t      ContentLen;     
  
  memcpy(&ListSize, (FlashAddressPtr + 4) , 4);
  memcpy(&ContentLen, (FlashAddressPtr + 10) , 2);
  

 

 

I get the warning only on the second "memcpy" not on the first.

THis warnig appears ONLY with optimization -O3. Not in O2, or none...

Is somebody can help me to understand what is my problem?

Regards

0 Kudos
1 Solution
2,730 Views
ErichStyger
Senior Contributor V

>>So It is an address value given by the linjer file corresponding to a memory specific defined zone...

No, not really. What you have here is a linker defined symbol, from which you can take the address (which is in fact the value of the virtual object). Actually it is not an object in the traditional sense, but a 'label'.

As you are using it as a pointer, I would expect that you would declare it as such, for example:

extern void *__base_MQTT_CERT_0;

I hope this helps?

Erich

View solution in original post

0 Kudos
6 Replies
2,731 Views
ErichStyger
Senior Contributor V

>>So It is an address value given by the linjer file corresponding to a memory specific defined zone...

No, not really. What you have here is a linker defined symbol, from which you can take the address (which is in fact the value of the virtual object). Actually it is not an object in the traditional sense, but a 'label'.

As you are using it as a pointer, I would expect that you would declare it as such, for example:

extern void *__base_MQTT_CERT_0;

I hope this helps?

Erich

0 Kudos
2,723 Views
arnogir
Senior Contributor II

Ok My mistake come from declare:

extern uint32_t __base_MQTT_CERT_0;

instead of

extern void *__base_MQTT_CERT_0;

Thank!

Tags (2)
0 Kudos
2,721 Views
arnogir
Senior Contributor II

In the same post, It still some other warning I will like to remove!

Can I ask you some help?

1) conversion from 'int' to 'uint8_t' {aka 'unsigned char'} may change value [-Wconversion]

static uint8_t DV_Rtc_iDayOfWeek(rtc_datetime_t DateTime)
{
  DateTime.day = (uint8_t)(DateTime.day += (uint8_t)DateTime.month < 3 ? DateTime.year-- : DateTime.year - 2, 23 * DateTime.month / 9 + DateTime.day + 4 + DateTime.year / 4 - DateTime.year / 100 + DateTime.year / 400) % 7;
  return (DateTime.day);
}

Warning is on the lime "DateTime.day = ..."

I get the "formula" directly on wikipedia. I'm not so familiar with this style of  "If, elsif.."

 

 

2)conversion from 'uint8_t' {aka 'unsigned char'} to 'unsigned char:4' may change value [-Wconversion]

Warnig is on this line

In .h:

typedef struct
{
  uint16_t ChannelSelect: 4;
  uint16_t BufferMode: 1;
  uint16_t RefDetect: 1;
  uint16_t RefSelect: 2;
  uint16_t GainSelect: 3;
  uint16_t Boost: 1;
  uint16_t UnipolarBipolar: 1;
  uint16_t BurnoutCurrent: 1;
  uint16_t VBIAS: 2;
} tCT_AD7795_ConfigurationRegisterBits;

typedef union
{
  tCT_AD7795_ConfigurationRegisterBits  Bits;
  uint16_t                              Data;
} tCT_AD7795_ConfigurationRegister;
typedef struct
{
  uint8_t ChannelSelect;
  uint8_t BufferMode;
  uint8_t RefDetect;
  uint8_t RefSelect;
  uint8_t GainSelect;
  int16_t NumericalGain;
  uint8_t Boost;
  uint8_t UnipolarBipolar;
  uint8_t BurnoutCurrent;
  uint8_t VBIAS;
  boolean ErrorGenerateReset;
  boolean CheckErrorMoveToFast;
  int32_t DefaultValue;
  tCT_AD7795_ThermocoupleType ThermoType;
} tCT_AD7795_ChannelCfg;
...

In .c
tCT_AD7795_ConfigurationRegister   CT_AD7795_iConfigurationRegister[CT_AD7795_NB_CHANNEL];

tCT_AD7795_ChannelCfg CT_AD7795_ChannelCfg[CT_AD7795_NB_CHANNEL] =
{
  /* CT_AD7795_CHANNEL0 : Configured to measure AIN1 */
  {
    /* ChannelSelect        */   CT_AD7795_CONFIG_CHANNEL_AIN1,
    /* BufferMode           */   CT_AD7795_CONFIG_BUF_ENABLE,
    /* RefDetect            */   CT_AD7795_CONFIG_REFDET_DISABLE,
    /* RefSelect            */   CT_AD7795_CONFIG_REFSEL_INTERNAL,
    /* GainSelect           */   CT_AD7795_CONFIG_GAIN_16,        /* If change here, change NumericalGain */
    /* NumericalGain        */   16,                              /* If change here, change GainSelect */
    /* Boost                */   CT_AD7795_CONFIG_BOOST_ENABLE,
    /* UnipolarBipolar      */   CT_AD7795_CONFIG_UB_BIPOLAR,
    /* BurnoutCurrent       */   CT_AD7795_CONFIG_BO_DISABLE,
    /* VBIAS                */   CT_AD7795_CONFIG_VBIAS_AIN1,
    /* ErrorGenerateReset   */   TRUE,
    /* CheckErrorMoveToFast */   FALSE,
    /* DefaultValue         */   0,
    /* ThermoType           */   CT_AD7795_THEMROCOUPLE_TYPE_K
  },
....

void MyFunc(...)
{
  CT_AD7795_iConfigurationRegister[ChannelId].Bits.ChannelSelect = CT_AD7795_ChannelCfg[ChannelId].ChannelSelect;   /* !!!! Warning on this line */
...}

 

I understand I try to "cast" byte (8bit) to a bitfield (ie 4 or 2 or 5 bits).

In my opinion, the code run correclty, but it should be great if the warning was controlled and removed.

What can I change to remove it? I have not idea!

 

Thank

0 Kudos
2,686 Views
arnogir
Senior Contributor II

Hi,

 

For the point 1, it should missed a cast. But with the "compressed form", it is not easy to see where it is.

So I used another method:

 

 

 

static uint8_t DV_Rtc_iDayOfWeek(rtc_datetime_t DateTime)
{
  /* https://fr.wikibooks.org/wiki/Curiosit%C3%A9s_math%C3%A9matiques/Trouver_le_jour_de_la_semaine_avec_une_date_donn%C3%A9e */
  
  int16_t 	c;
  int16_t 	a;
  int16_t 	m;
  int16_t   Result;
  
  c = (int16_t)(14 - DateTime.month) / 12;
  a = (int16_t)DateTime.year - c;
  m = (int16_t)(DateTime.month + (12 * c) - 2);
  
  Result = (int16_t)( DateTime.day + a + (a / 4) - (a / 100) + (a / 400) + (31 * m) / 12 ) % 7;
  
  return ((uint8_t)Result);
}

 

 

Stay the affectation of uint16_t:x from an uint8_t... I looked for this problem, it seem a recurent unsolved problem.

0 Kudos
2,732 Views
arnogir
Senior Contributor II

Thank for reply.

 

My call is:

 

extern uint32_t __base_MQTT_CERT_0;

main()
{
  ...
  MyFunc((uint8_t*)&__base_MQTT_CERT_0);
  ..
}

Linker file:
...
  __base_MQTT_CERT_0 = 0x3dc00  ; /* MQTT_CERT_0 */  
...

 

MCUXpresso config:

arnogir_0-1680866437376.png

 

So It is an address value given by the linjer file corresponding to a memory specific defined zone...

How can I resolve this warning?

0 Kudos
2,735 Views
ErichStyger
Senior Contributor V

The problem is with 'FlashAddressPtr': you are passing the address of an object to your MyFunc with FlashAddressPtr which points to an object which is not large enough. So a classic 'array out-of-bounds' programming error.

You only get the warning with higher optimizations, because here the compiler does constant propagation and variable analysis cross function calls.

So I recommend you check all calls to MyFunc() and check if you have passed an object of adequate size passed.

To illustrate the case, consider following code:

static bool MyFunc(const uint8_t* FlashAddressPtr)
{
 // const uint8_t Header[] = {0xF1, 0xF1, 0x01, 0x00};  /* Magic Code + the number of Certificate file... */
  uint32_t      ListSize;
  uint16_t      ContentLen;

  memcpy(&ListSize, (FlashAddressPtr + 4) , 4);
  memcpy(&ContentLen, (FlashAddressPtr + 10) , 2);
  return false;
}

static const uint32_t var = 0x10;

int main(void) {
  (void)MyFunc((uint8_t *)&var);

 

Here you pass the address of an object to your function, which is not large enough for your (FlashAddressPtr + 10): your object has to be at least 10+2 bytes large.

I hope this helps?

Erich

0 Kudos