Search code examples
carraysmemcpy

how the warning Possible data overrun for function 'memcpy' happens and how to fix it?


I have the following code:

#define NUM_PEOPLE 20
#define TIME_PEOPLE 10
typedef struct
{
    int name;
    int age;
} People

typedef struct
{
    int number;
    int post;
} Contact;

typedef struct
{
      int             number;
      Pepole          people[TIME_PEOPLE][NUM_PEOPLE];
      Contact         contact[NUM_PEOPLE];
} Master;

typedef struct
{
      int             number;
      People          people[NUM_PEOPLE][NUM_PEOPLE];
      Contact         contact[NUM_PEOPLE];
} Info;

Info info;
Master master;

int counter = 1
int size;
int offset = 0;

while(counter > 0)
{  

      size = TIME_PEOPLE;

      if(counter == 1)
      {
     size = NUM_PEOPLE - (TIME_PEOPLE * (offset + 1));
      }

      memcpy(&info.people[TIME_PEOPLE + TIME_PEOPLE * offset][0], &master.people[0][0],
         sizeof(People) * size * NUM_PEOPLE);
      offset ++;
      counter --;
}

but I got the following warning:

Warning 669: Possible data overrun for function 'memcpy(void *, const void *, unsigned int)', argument 3 ,

I made this code, because NUM_PEOPLE could be changed to less than TIME_PEOPLE, then how this warning happens and how to fix it?

P.S. If TIME_PEOPLE be changed to 8, this means we need to copy three times to fullfill the info


Solution

  • Consider what happens when offset is incremented to one. This reference:

    &info.people[TIME_PEOPLE + TIME_PEOPLE * offset][0]
    

    translates to this:

    &info.people[20][0]
    

    And since the info.people array only has NUM_PEOPLE (i.e. 20) elements, that is already pointing past the end.

    Given the way the code is currently written, that will never happen since the loop is only ever executed once, but the compiler might not take that into account. What is the point of having that loop if it's only ever going to be executed once and the offset will only ever be zero?

    It looks to me like that array reference should really have been:

    &info.people[TIME_PEOPLE * offset][0]
    

    The size calculation should have been:

    size = NUM_PEOPLE - (TIME_PEOPLE * offset);
    

    And the counter should probably have been initialised to something like this:

    int counter = ceil((float)NUM_PEOPLE/TIME_PEOPLE);
    

    But it's hard to say without knowing exactly what you're trying to do. I just know that what you currently have implemented doesn't make any sense.